From 56fe54d1afb5f31ee64422416e977205d73c3afc Mon Sep 17 00:00:00 2001 From: mrbird <852252810@qq.com> Date: Fri, 14 Sep 2018 09:04:22 +0800 Subject: [PATCH] =?UTF-8?q?Spring=20Security=E6=B7=BB=E5=8A=A0=E8=AE=B0?= =?UTF-8?q?=E4=BD=8F=E6=88=91=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 37.Spring-Security-RememberMe/pom.xml | 68 +++++++++++++ .../java/cc/mrbird/SecurityApplication.java | 12 +++ .../main/java/cc/mrbird/domain/MyUser.java | 67 +++++++++++++ .../MyAuthenticationFailureHandler.java | 29 ++++++ .../MyAuthenticationSucessHandler.java | 40 ++++++++ .../browser/BrowserSecurityConfig.java | 75 ++++++++++++++ .../security/browser/UserDetailService.java | 32 ++++++ .../cc/mrbird/validate/code/ImageCode.java | 53 ++++++++++ .../validate/code/ValidateCodeException.java | 11 +++ .../validate/code/ValidateCodeFilter.java | 63 ++++++++++++ .../controller/BrowserSecurityController.java | 39 ++++++++ .../mrbird/web/controller/TestController.java | 20 ++++ .../web/controller/ValidateController.java | 82 ++++++++++++++++ .../src/main/resources/application.yml | 12 +++ .../main/resources/resources/css/login.css | 97 +++++++++++++++++++ .../src/main/resources/resources/login.html | 23 +++++ 16 files changed, 723 insertions(+) create mode 100644 37.Spring-Security-RememberMe/pom.xml create mode 100644 37.Spring-Security-RememberMe/src/main/java/cc/mrbird/SecurityApplication.java create mode 100644 37.Spring-Security-RememberMe/src/main/java/cc/mrbird/domain/MyUser.java create mode 100644 37.Spring-Security-RememberMe/src/main/java/cc/mrbird/handler/MyAuthenticationFailureHandler.java create mode 100644 37.Spring-Security-RememberMe/src/main/java/cc/mrbird/handler/MyAuthenticationSucessHandler.java create mode 100644 37.Spring-Security-RememberMe/src/main/java/cc/mrbird/security/browser/BrowserSecurityConfig.java create mode 100644 37.Spring-Security-RememberMe/src/main/java/cc/mrbird/security/browser/UserDetailService.java create mode 100644 37.Spring-Security-RememberMe/src/main/java/cc/mrbird/validate/code/ImageCode.java create mode 100644 37.Spring-Security-RememberMe/src/main/java/cc/mrbird/validate/code/ValidateCodeException.java create mode 100644 37.Spring-Security-RememberMe/src/main/java/cc/mrbird/validate/code/ValidateCodeFilter.java create mode 100644 37.Spring-Security-RememberMe/src/main/java/cc/mrbird/web/controller/BrowserSecurityController.java create mode 100644 37.Spring-Security-RememberMe/src/main/java/cc/mrbird/web/controller/TestController.java create mode 100644 37.Spring-Security-RememberMe/src/main/java/cc/mrbird/web/controller/ValidateController.java create mode 100644 37.Spring-Security-RememberMe/src/main/resources/application.yml create mode 100644 37.Spring-Security-RememberMe/src/main/resources/resources/css/login.css create mode 100644 37.Spring-Security-RememberMe/src/main/resources/resources/login.html diff --git a/37.Spring-Security-RememberMe/pom.xml b/37.Spring-Security-RememberMe/pom.xml new file mode 100644 index 00000000..dac82380 --- /dev/null +++ b/37.Spring-Security-RememberMe/pom.xml @@ -0,0 +1,68 @@ + + + 4.0.0 + + cc.mrbird + Security + 1.0-SNAPSHOT + jar + + Security + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 1.5.14.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.social + spring-social-config + + + org.springframework.boot + spring-boot-starter-jdbc + + + mysql + mysql-connector-java + + + + org.apache.commons + commons-lang3 + 3.7 + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/SecurityApplication.java b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/SecurityApplication.java new file mode 100644 index 00000000..47409349 --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/SecurityApplication.java @@ -0,0 +1,12 @@ +package cc.mrbird; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SecurityApplication { + + public static void main(String[] args) { + SpringApplication.run(SecurityApplication.class, args); + } +} diff --git a/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/domain/MyUser.java b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/domain/MyUser.java new file mode 100644 index 00000000..dee4f7ff --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/domain/MyUser.java @@ -0,0 +1,67 @@ +package cc.mrbird.domain; + +import java.io.Serializable; + +public class MyUser implements Serializable { + private static final long serialVersionUID = 3497935890426858541L; + + private String userName; + + private String password; + + private boolean accountNonExpired = true; + + private boolean accountNonLocked= true; + + private boolean credentialsNonExpired= true; + + private boolean enabled= true; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public boolean isAccountNonExpired() { + return accountNonExpired; + } + + public void setAccountNonExpired(boolean accountNonExpired) { + this.accountNonExpired = accountNonExpired; + } + + public boolean isAccountNonLocked() { + return accountNonLocked; + } + + public void setAccountNonLocked(boolean accountNonLocked) { + this.accountNonLocked = accountNonLocked; + } + + public boolean isCredentialsNonExpired() { + return credentialsNonExpired; + } + + public void setCredentialsNonExpired(boolean credentialsNonExpired) { + this.credentialsNonExpired = credentialsNonExpired; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } +} diff --git a/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/handler/MyAuthenticationFailureHandler.java b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/handler/MyAuthenticationFailureHandler.java new file mode 100644 index 00000000..22127b47 --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/handler/MyAuthenticationFailureHandler.java @@ -0,0 +1,29 @@ +package cc.mrbird.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { + + @Autowired + private ObjectMapper mapper; + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, + AuthenticationException exception) throws IOException { + response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); + response.setContentType("application/json;charset=utf-8"); + response.getWriter().write(mapper.writeValueAsString(exception.getMessage())); + } +} diff --git a/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/handler/MyAuthenticationSucessHandler.java b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/handler/MyAuthenticationSucessHandler.java new file mode 100644 index 00000000..8dc29d39 --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/handler/MyAuthenticationSucessHandler.java @@ -0,0 +1,40 @@ +package cc.mrbird.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.DefaultRedirectStrategy; +import org.springframework.security.web.RedirectStrategy; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.savedrequest.RequestCache; +import org.springframework.security.web.savedrequest.SavedRequest; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class MyAuthenticationSucessHandler implements AuthenticationSuccessHandler { + + // private RequestCache requestCache = new HttpSessionRequestCache(); + + private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); + // + // @Autowired + // private ObjectMapper mapper; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws IOException { + // response.setContentType("application/json;charset=utf-8"); + // response.getWriter().write(mapper.writeValueAsString(authentication)); + // SavedRequest savedRequest = requestCache.getRequest(request, response); + // System.out.println(savedRequest.getRedirectUrl()); + // redirectStrategy.sendRedirect(request, response, savedRequest.getRedirectUrl()); + redirectStrategy.sendRedirect(request, response, "/index"); + } +} diff --git a/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/security/browser/BrowserSecurityConfig.java b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/security/browser/BrowserSecurityConfig.java new file mode 100644 index 00000000..a481ec93 --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/security/browser/BrowserSecurityConfig.java @@ -0,0 +1,75 @@ +package cc.mrbird.security.browser; + +import cc.mrbird.handler.MyAuthenticationFailureHandler; +import cc.mrbird.handler.MyAuthenticationSucessHandler; +import cc.mrbird.validate.code.ValidateCodeFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl; +import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; + +import javax.sql.DataSource; + +@Configuration +public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private MyAuthenticationSucessHandler authenticationSucessHandler; + + @Autowired + private MyAuthenticationFailureHandler authenticationFailureHandler; + + @Autowired + private ValidateCodeFilter validateCodeFilter; + + @Autowired + private UserDetailService userDetailService; + + @Autowired + private DataSource dataSource; + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public PersistentTokenRepository persistentTokenRepository() { + JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl(); + jdbcTokenRepository.setDataSource(dataSource); + jdbcTokenRepository.setCreateTableOnStartup(false); + return jdbcTokenRepository; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + + http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加验证码校验过滤器 + .formLogin() // 表单登录 + // http.httpBasic() // HTTP Basic + .loginPage("/authentication/require") // 登录跳转 URL + .loginProcessingUrl("/login") // 处理表单登录 URL + .successHandler(authenticationSucessHandler) // 处理登录成功 + .failureHandler(authenticationFailureHandler) // 处理登录失败 + .and() + .rememberMe() + .tokenRepository(persistentTokenRepository()) // 配置 token 持久化仓库 + .tokenValiditySeconds(3600) // remember 过期时间,单为秒 + .userDetailsService(userDetailService) // 处理自动登录逻辑 + .and() + .authorizeRequests() // 授权配置 + .antMatchers("/authentication/require", + "/login.html", + "/code/image").permitAll() // 无需认证的请求路径 + .anyRequest() // 所有请求 + .authenticated() // 都需要认证 + .and() + .csrf().disable(); + } +} diff --git a/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/security/browser/UserDetailService.java b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/security/browser/UserDetailService.java new file mode 100644 index 00000000..58992aa1 --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/security/browser/UserDetailService.java @@ -0,0 +1,32 @@ +package cc.mrbird.security.browser; + +import cc.mrbird.domain.MyUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class UserDetailService implements UserDetailsService { + + @Autowired + private PasswordEncoder passwordEncoder; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + // 模拟一个用户,替代数据库获取逻辑 + MyUser user = new MyUser(); + user.setUserName(username); + user.setPassword(this.passwordEncoder.encode("123456")); + // 输出加密后的密码 + System.out.println(user.getPassword()); + + return new User(username, user.getPassword(), user.isEnabled(), + user.isAccountNonExpired(), user.isCredentialsNonExpired(), + user.isAccountNonLocked(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin")); + } +} diff --git a/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/validate/code/ImageCode.java b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/validate/code/ImageCode.java new file mode 100644 index 00000000..28850b82 --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/validate/code/ImageCode.java @@ -0,0 +1,53 @@ +package cc.mrbird.validate.code; + +import java.awt.image.BufferedImage; +import java.time.LocalDateTime; + +public class ImageCode { + + private BufferedImage image; + + private String code; + + private LocalDateTime expireTime; + + public ImageCode(BufferedImage image, String code, int expireIn) { + this.image = image; + this.code = code; + this.expireTime = LocalDateTime.now().plusSeconds(expireIn); + } + + public ImageCode(BufferedImage image, String code, LocalDateTime expireTime) { + this.image = image; + this.code = code; + this.expireTime = expireTime; + } + + boolean isExpire() { + return LocalDateTime.now().isAfter(expireTime); + } + + public BufferedImage getImage() { + return image; + } + + public void setImage(BufferedImage image) { + this.image = image; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public LocalDateTime getExpireTime() { + return expireTime; + } + + public void setExpireTime(LocalDateTime expireTime) { + this.expireTime = expireTime; + } +} diff --git a/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/validate/code/ValidateCodeException.java b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/validate/code/ValidateCodeException.java new file mode 100644 index 00000000..2ce2ceca --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/validate/code/ValidateCodeException.java @@ -0,0 +1,11 @@ +package cc.mrbird.validate.code; + +import org.springframework.security.core.AuthenticationException; + +public class ValidateCodeException extends AuthenticationException { + private static final long serialVersionUID = 5022575393500654458L; + + ValidateCodeException(String message) { + super(message); + } +} diff --git a/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/validate/code/ValidateCodeFilter.java b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/validate/code/ValidateCodeFilter.java new file mode 100644 index 00000000..742eafd4 --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/validate/code/ValidateCodeFilter.java @@ -0,0 +1,63 @@ +package cc.mrbird.validate.code; + +import cc.mrbird.web.controller.ValidateController; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.social.connect.web.HttpSessionSessionStrategy; +import org.springframework.social.connect.web.SessionStrategy; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.ServletRequestBindingException; +import org.springframework.web.bind.ServletRequestUtils; +import org.springframework.web.context.request.ServletWebRequest; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class ValidateCodeFilter extends OncePerRequestFilter { + + @Autowired + private AuthenticationFailureHandler authenticationFailureHandler; + + private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy(); + + @Override + protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { + if (StringUtils.equalsIgnoreCase("/login", httpServletRequest.getRequestURI()) + && StringUtils.equalsIgnoreCase(httpServletRequest.getMethod(), "post")) { + try { + validateCode(new ServletWebRequest(httpServletRequest)); + } catch (ValidateCodeException e) { + authenticationFailureHandler.onAuthenticationFailure(httpServletRequest, httpServletResponse, e); + return; + } + } + filterChain.doFilter(httpServletRequest, httpServletResponse); + } + + private void validateCode(ServletWebRequest servletWebRequest) throws ServletRequestBindingException { + ImageCode codeInSession = (ImageCode) sessionStrategy.getAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE); + String codeInRequest = ServletRequestUtils.getStringParameter(servletWebRequest.getRequest(), "imageCode"); + + if (StringUtils.isBlank(codeInRequest)) { + throw new ValidateCodeException("验证码不能为空!"); + } + if (codeInSession == null) { + throw new ValidateCodeException("验证码不存在!"); + } + if (codeInSession.isExpire()) { + sessionStrategy.removeAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE); + throw new ValidateCodeException("验证码已过期!"); + } + if (!StringUtils.equalsIgnoreCase(codeInSession.getCode(), codeInRequest)) { + throw new ValidateCodeException("验证码不正确!"); + } + sessionStrategy.removeAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE); + + } +} diff --git a/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/web/controller/BrowserSecurityController.java b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/web/controller/BrowserSecurityController.java new file mode 100644 index 00000000..b198589b --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/web/controller/BrowserSecurityController.java @@ -0,0 +1,39 @@ +package cc.mrbird.web.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.security.web.DefaultRedirectStrategy; +import org.springframework.security.web.RedirectStrategy; +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.savedrequest.RequestCache; +import org.springframework.security.web.savedrequest.SavedRequest; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author MrBird + */ +@RestController +public class BrowserSecurityController { + + private RequestCache requestCache = new HttpSessionRequestCache(); + + private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); + + @GetMapping("/authentication/require") + @ResponseStatus(HttpStatus.UNAUTHORIZED) + public String requireAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException { + SavedRequest savedRequest = requestCache.getRequest(request, response); + if (savedRequest != null) { + String targetUrl = savedRequest.getRedirectUrl(); + if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")) + redirectStrategy.sendRedirect(request, response, "/login.html"); + } + return "访问的资源需要身份认证!"; + } +} diff --git a/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/web/controller/TestController.java b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/web/controller/TestController.java new file mode 100644 index 00000000..b677e616 --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/web/controller/TestController.java @@ -0,0 +1,20 @@ +package cc.mrbird.web.controller; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TestController { + @GetMapping("hello") + public String hello() { + return "hello spring security"; + } + + @GetMapping("index") + public Object index(Authentication authentication) { + // return SecurityContextHolder.getContext().getAuthentication(); + return authentication; + } +} diff --git a/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/web/controller/ValidateController.java b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/web/controller/ValidateController.java new file mode 100644 index 00000000..be2a9d4c --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/java/cc/mrbird/web/controller/ValidateController.java @@ -0,0 +1,82 @@ +package cc.mrbird.web.controller; + +import cc.mrbird.validate.code.ImageCode; +import org.springframework.social.connect.web.HttpSessionSessionStrategy; +import org.springframework.social.connect.web.SessionStrategy; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.ServletWebRequest; + +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.Random; + +@RestController +public class ValidateController { + + public final static String SESSION_KEY_IMAGE_CODE = "SESSION_KEY_IMAGE_CODE"; + + private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy(); + + @GetMapping("/code/image") + public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException { + ImageCode imageCode = createImageCode(); + sessionStrategy.setAttribute(new ServletWebRequest(request), SESSION_KEY_IMAGE_CODE, imageCode); + ImageIO.write(imageCode.getImage(), "jpeg", response.getOutputStream()); + } + + private ImageCode createImageCode() { + int width = 100; // 验证码图片宽度 + int height = 36; // 验证码图片长度 + int length = 4; // 验证码位数 + int expireIn = 60; // 验证码有效时间 60s + + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + + Graphics g = image.getGraphics(); + + Random random = new Random(); + + g.setColor(getRandColor(200, 250)); + g.fillRect(0, 0, width, height); + g.setFont(new Font("Times New Roman", Font.ITALIC, 20)); + g.setColor(getRandColor(160, 200)); + for (int i = 0; i < 155; i++) { + int x = random.nextInt(width); + int y = random.nextInt(height); + int xl = random.nextInt(12); + int yl = random.nextInt(12); + g.drawLine(x, y, x + xl, y + yl); + } + + StringBuilder sRand = new StringBuilder(); + for (int i = 0; i < length; i++) { + String rand = String.valueOf(random.nextInt(10)); + sRand.append(rand); + g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110))); + g.drawString(rand, 13 * i + 6, 16); + } + + g.dispose(); + + return new ImageCode(image, sRand.toString(), expireIn); + } + + private Color getRandColor(int fc, int bc) { + Random random = new Random(); + if (fc > 255) + fc = 255; + + if (bc > 255) + bc = 255; + int r = fc + random.nextInt(bc - fc); + int g = fc + random.nextInt(bc - fc); + int b = fc + random.nextInt(bc - fc); + return new Color(r, g, b); + } + +} diff --git a/37.Spring-Security-RememberMe/src/main/resources/application.yml b/37.Spring-Security-RememberMe/src/main/resources/application.yml new file mode 100644 index 00000000..8d8dee06 --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/resources/application.yml @@ -0,0 +1,12 @@ +security: + basic: + enabled: true + + + +spring: + datasource: + driver-class-name: com.mysql.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/security?useUnicode=yes&characterEncoding=UTF-8&useSSL=false + username: root + password: 123456 \ No newline at end of file diff --git a/37.Spring-Security-RememberMe/src/main/resources/resources/css/login.css b/37.Spring-Security-RememberMe/src/main/resources/resources/css/login.css new file mode 100644 index 00000000..52d16991 --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/resources/resources/css/login.css @@ -0,0 +1,97 @@ +.login-page { + width: 360px; + padding: 8% 0 0; + margin: auto; +} +.form { + position: relative; + z-index: 1; + background: #ffffff; + max-width: 360px; + margin: 0 auto 100px; + padding: 45px; + text-align: center; + box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24); +} +.form input { + outline: 0; + background: #f2f2f2; + width: 100%; + border: 0; + margin: 0 0 15px; + padding: 15px; + box-sizing: border-box; + font-size: 14px; +} +.form button { + text-transform: uppercase; + outline: 0; + background: #4caf50; + width: 100%; + border: 0; + padding: 15px; + color: #ffffff; + font-size: 14px; + -webkit-transition: all 0.3 ease; + transition: all 0.3 ease; + cursor: pointer; +} +.form button:hover, +.form button:active, +.form button:focus { + background: #43a047; +} +.form .message { + margin: 15px 0 0; + color: #b3b3b3; + font-size: 12px; +} +.form .message a { + color: #4caf50; + text-decoration: none; +} +.form .register-form { + display: none; +} +.container { + position: relative; + z-index: 1; + max-width: 300px; + margin: 0 auto; +} +.container:before, +.container:after { + content: ""; + display: block; + clear: both; +} +.container .info { + margin: 50px auto; + text-align: center; +} +.container .info h1 { + margin: 0 0 15px; + padding: 0; + font-size: 36px; + font-weight: 300; + color: #1a1a1a; +} +.container .info span { + color: #4d4d4d; + font-size: 12px; +} +.container .info span a { + color: #000000; + text-decoration: none; +} +.container .info span .fa { + color: #ef3b3a; +} +body { + background: #76b852; /* fallback for old browsers */ + background: -webkit-linear-gradient(right, #76b852, #8dc26f); + background: -moz-linear-gradient(right, #76b852, #8dc26f); + background: -o-linear-gradient(right, #76b852, #8dc26f); + background: linear-gradient(to left, #76b852, #8dc26f); + font-family: Lato,"PingFang SC","Microsoft YaHei",sans-serif; +} diff --git a/37.Spring-Security-RememberMe/src/main/resources/resources/login.html b/37.Spring-Security-RememberMe/src/main/resources/resources/login.html new file mode 100644 index 00000000..75d318c4 --- /dev/null +++ b/37.Spring-Security-RememberMe/src/main/resources/resources/login.html @@ -0,0 +1,23 @@ + + + + + 登录 + + + +
+
+

账户登录

+ + + + + + + 记住我 + +
+
+ + \ No newline at end of file