系列博文html
项目已上传至guthub 传送门java
JavaWeb-SpringSecurity初认识 传送门mysql
JavaWeb-SpringSecurity在数据库中查询登录用户 传送门git
JavaWeb-SpringSecurity自定义登录页面 传送门github
JavaWeb-SpringSecurity实现需求-判断请求是否以html结尾 传送门web
JavaWeb-SpringSecurity自定义登录配置 传送门spring
JavaWeb-SpringSecurity图片验证ImageCode 传送门sql
JavaWeb-SpringSecurity记住我功能 传送门数据库
JavaWeb-SpringSecurity使用短信验证码登录 传送门apache
使用Restful自定义登录配置
自定义登录成功后的Handler
添加hhandler类库,建立LoginSuccessHandler.class,实现用户成功登录Handler
@Override //登录成功以后会调用的函数 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, //封装了咱们的认证信息(发起的认证请求(ip,session),认证成功后的用户信息) Authentication authentication) throws IOException, ServletException { // TODO Auto-generated method stub System.out.println("登录成功"); response.setContentType("application/json;charset=UTF-8"); //将咱们authentication转换为json经过response对象以application/json写到页面 response.getWriter().write(objectMapper.writeValueAsString(authentication)); }
在SecurityConfig.java中配置configure()方法
protected void configure(HttpSecurity http) throws Exception{ //表单验证(身份认证) http.formLogin() //自定义登录页面 .loginPage("/require") //若是URL为loginPage,则用SpringSecurity中自带的过滤器去处理该请求 .loginProcessingUrl("/loginPage") //配置登录成功调用loginSuccessHandler .successHandler(loginSuccessHandler) .and() //请求受权 .authorizeRequests() //在访问咱们的URL时,咱们是不须要省份认证,能够当即访问 .antMatchers("/login.html","/require").permitAll() //全部请求都被拦截,跳转到(/login请求中) .anyRequest() //都须要咱们身份认证 .authenticated() //SpringSecurity保护机制 .and().csrf().disable(); }
package com.Gary.GaryRESTful.handler; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; @Component public class LoginSuccessHandler implements AuthenticationSuccessHandler{ //将咱们的authentication转换为json所须要的类 @Autowired private ObjectMapper objectMapper; @Override //登录成功以后会调用的函数 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, //封装了咱们的认证信息(发起的认证请求(ip,session),认证成功后的用户信息) Authentication authentication) throws IOException, ServletException { // TODO Auto-generated method stub System.out.println("登录成功"); response.setContentType("application/json;charset=UTF-8"); //将咱们authentication转换为json经过response对象以application/json写到页面 response.getWriter().write(objectMapper.writeValueAsString(authentication)); } }
package com.Gary.GaryRESTful.config; 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 com.Gary.GaryRESTful.handler.LoginSuccessHandler; //Web应用安全适配器 @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter{ //告诉SpringSecurity密码用什么加密的 @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Autowired private LoginSuccessHandler loginSuccessHandler; protected void configure(HttpSecurity http) throws Exception{ //表单验证(身份认证) http.formLogin() //自定义登录页面 .loginPage("/require") //若是URL为loginPage,则用SpringSecurity中自带的过滤器去处理该请求 .loginProcessingUrl("/loginPage") //配置登录成功调用loginSuccessHandler .successHandler(loginSuccessHandler) .and() //请求受权 .authorizeRequests() //在访问咱们的URL时,咱们是不须要省份认证,能够当即访问 .antMatchers("/login.html","/require").permitAll() //全部请求都被拦截,跳转到(/login请求中) .anyRequest() //都须要咱们身份认证 .authenticated() //SpringSecurity保护机制 .and().csrf().disable(); } }
//用户权限 authorities: //认证请求的信息(ip,session) details //用户是否已经经过了咱们的身份认证 authenticated //UserDetails principal //用户输入的密码 credentials //用户名 name
用户登录失败后的Handler
@Override //登录不成功产生的错误 public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { System.out.println("登录失败"); //设置返回的状态码 500 response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR); response.setContentType("application/json;charset=UTF-8"); //将咱们authentication转换为json经过response对象以application/json写到页面 response.getWriter().write(objectMapper.writeValueAsString(exception)); }
在SecurityConfig.java中配置configure()方法
protected void configure(HttpSecurity http) throws Exception{ //表单验证(身份认证) http.formLogin() //自定义登录页面 .loginPage("/require") //若是URL为loginPage,则用SpringSecurity中自带的过滤器去处理该请求 .loginProcessingUrl("/loginPage") //配置登录成功调用loginSuccessHandler .successHandler(loginSuccessHandler) //配置登录失败调用loginFailureHandler .failureHandler(loginFailureHandler) .and() //请求受权 .authorizeRequests() //在访问咱们的URL时,咱们是不须要省份认证,能够当即访问 .antMatchers("/login.html","/require").permitAll() //全部请求都被拦截,跳转到(/login请求中) .anyRequest() //都须要咱们身份认证 .authenticated() //SpringSecurity保护机制 .and().csrf().disable(); }
package com.Gary.GaryRESTful.handler; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.http.HttpStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; @Component public class LoginFailureHandler implements AuthenticationFailureHandler{ //将咱们的authentication转换为json所须要的类 @Autowired private ObjectMapper objectMapper; @Override //登录不成功产生的错误 public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { System.out.println("登录失败"); //设置返回的状态码 500 response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR); response.setContentType("application/json;charset=UTF-8"); //将咱们authentication转换为json经过response对象以application/json写到页面 response.getWriter().write(objectMapper.writeValueAsString(exception)); } }
package com.Gary.GaryRESTful.config; 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 com.Gary.GaryRESTful.handler.LoginFailureHandler; import com.Gary.GaryRESTful.handler.LoginSuccessHandler; //Web应用安全适配器 @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter{ //告诉SpringSecurity密码用什么加密的 @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Autowired private LoginSuccessHandler loginSuccessHandler; @Autowired private LoginFailureHandler loginFailureHandler; protected void configure(HttpSecurity http) throws Exception{ //表单验证(身份认证) http.formLogin() //自定义登录页面 .loginPage("/require") //若是URL为loginPage,则用SpringSecurity中自带的过滤器去处理该请求 .loginProcessingUrl("/loginPage") //配置登录成功调用loginSuccessHandler .successHandler(loginSuccessHandler) //配置登录失败调用loginFailureHandler .failureHandler(loginFailureHandler) .and() //请求受权 .authorizeRequests() //在访问咱们的URL时,咱们是不须要省份认证,能够当即访问 .antMatchers("/login.html","/require").permitAll() //全部请求都被拦截,跳转到(/login请求中) .anyRequest() //都须要咱们身份认证 .authenticated() //SpringSecurity保护机制 .and().csrf().disable(); } }
用户自定义登录配置
在application.properties中配置gary.security.loginType为JSON
当用户登录成功时,当用户打印出登录成功信息(JSON格式)
@Override //登录成功以后会调用的函数 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, //封装了咱们的认证信息(发起的认证请求(ip,session),认证成功后的用户信息) Authentication authentication) throws IOException, ServletException { // TODO Auto-generated method stub System.out.println("登录成功"); System.out.println(garySecurityProperties.getLoginType()); response.setContentType("application/json;charset=UTF-8"); //将咱们authentication转换为json经过response对象以application/json写到页面 response.getWriter().write(objectMapper.writeValueAsString(authentication)); }
#datasource spring.datasource.url=jdbc:mysql:///springsecurity?serverTimezone=UTC&characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.dricer-class-name=com.mysql.jdbc.Driver #jpa #打印出数据库语句 spring.jpa.show-sql=true #更新数据库表 spring.jpa.hibernate.ddl-auto=update gary.security.loginType = JSON
package com.Gary.GaryRESTful.properties; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "gary.security") public class GarySecurityProperties { //LoginType登录的方式,默认为JSON(restful设计风格) private LoginType loginType = LoginType.JSON; public LoginType getLoginType() { return loginType; } public void setLoginType(LoginType loginType) { this.loginType = loginType; } }
package com.Gary.GaryRESTful.properties; //登录的方式 public enum LoginType { JSON, REDIRECT }
package com.Gary.GaryRESTful.properties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; @Configuration //让咱们的配置生效 @EnableConfigurationProperties(GarySecurityProperties.class) public class GarySecurityConfig { }
package com.Gary.GaryRESTful.handler; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.http.HttpStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; @Component public class LoginFailureHandler implements AuthenticationFailureHandler{ //将咱们的authentication转换为json所须要的类 @Autowired private ObjectMapper objectMapper; @Override //登录不成功产生的错误 public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { System.out.println("登录失败"); //设置返回的状态码 500 SC_INTERNAL_SERVER_ERROR response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR); response.setContentType("application/json;charset=UTF-8"); //将咱们authentication转换为json经过response对象以application/json写到页面 response.getWriter().write(objectMapper.writeValueAsString(exception)); } }
package com.Gary.GaryRESTful.handler; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Component; import com.Gary.GaryRESTful.properties.GarySecurityProperties; import com.fasterxml.jackson.databind.ObjectMapper; @Component public class LoginSuccessHandler implements AuthenticationSuccessHandler{ //将咱们的authentication转换为json所须要的类 @Autowired private ObjectMapper objectMapper; @Autowired private GarySecurityProperties garySecurityProperties; @Override //登录成功以后会调用的函数 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, //封装了咱们的认证信息(发起的认证请求(ip,session),认证成功后的用户信息) Authentication authentication) throws IOException, ServletException { // TODO Auto-generated method stub System.out.println("登录成功"); System.out.println(garySecurityProperties.getLoginType()); response.setContentType("application/json;charset=UTF-8"); //将咱们authentication转换为json经过response对象以application/json写到页面 response.getWriter().write(objectMapper.writeValueAsString(authentication)); } }
为提升软件通用性
在application.properties中配置gary.security.loginType为REDIRECT(重定向)
当用户登录成功时,LoginSuccessHandler重定向到default.jsp继承SavedRequestAwareAuthenticationSuccessHandler,SavedRequestAwareAuthenticationSuccessHandler为SpringSecurity默认处理机制
@Override //登录成功以后会调用的函数 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, //封装了咱们的认证信息(发起的认证请求(ip,session),认证成功后的用户信息) Authentication authentication) throws IOException, ServletException { // TODO Auto-generated method stub System.out.println("登录成功"); if(LoginType.JSON.equals(garySecurityProperties.getLoginType())) { response.setContentType("application/json;charset=UTF-8"); //将咱们authentication转换为json经过response对象以application/json写到页面 response.getWriter().write(objectMapper.writeValueAsString(authentication)); } else { //调用父类中的方法,跳转到其它页面 super.onAuthenticationSuccess(request, response, authentication); } }
当用户登录失败时,springsecurity进行对请求的拦截
//登录不成功产生的错误 public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { System.out.println("登录失败"); if(LoginType.JSON.equals(garySecurityProperties.getLoginType())) { //设置返回的状态码 500 SC_INTERNAL_SERVER_ERROR response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR); response.setContentType("application/json;charset=UTF-8"); //将咱们authentication转换为json经过response对象以application/json写到页面 response.getWriter().write(objectMapper.writeValueAsString(exception)); } else { //调用父类中的方法,跳转到其它页面 super.onAuthenticationFailure(request, response, exception); }
#datasource spring.datasource.url=jdbc:mysql:///springsecurity?serverTimezone=UTC&characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.dricer-class-name=com.mysql.jdbc.Driver #jpa #打印出数据库语句 spring.jpa.show-sql=true #更新数据库表 spring.jpa.hibernate.ddl-auto=update gary.security.loginType = REDIRECT
package com.Gary.GaryRESTful.handler; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.stereotype.Component; import com.Gary.GaryRESTful.properties.GarySecurityProperties; import com.Gary.GaryRESTful.properties.LoginType; import com.fasterxml.jackson.databind.ObjectMapper; @Component //SavedRequestAwareAuthenticationSuccessHandler为SpringSecurity默认处理机制 public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler{ //将咱们的authentication转换为json所须要的类 @Autowired private ObjectMapper objectMapper; @Autowired private GarySecurityProperties garySecurityProperties; @Override //登录成功以后会调用的函数 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, //封装了咱们的认证信息(发起的认证请求(ip,session),认证成功后的用户信息) Authentication authentication) throws IOException, ServletException { // TODO Auto-generated method stub System.out.println("登录成功"); if(LoginType.JSON.equals(garySecurityProperties.getLoginType())) { response.setContentType("application/json;charset=UTF-8"); //将咱们authentication转换为json经过response对象以application/json写到页面 response.getWriter().write(objectMapper.writeValueAsString(authentication)); } else { //调用父类中的方法,跳转到其它页面 super.onAuthenticationSuccess(request, response, authentication); } } }
package com.Gary.GaryRESTful.handler; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.http.HttpStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; import org.springframework.stereotype.Component; import com.Gary.GaryRESTful.properties.GarySecurityProperties; import com.Gary.GaryRESTful.properties.LoginType; import com.fasterxml.jackson.databind.ObjectMapper; @Component //springsecurity默认处理器 public class LoginFailureHandler extends SimpleUrlAuthenticationFailureHandler{ //将咱们的authentication转换为json所须要的类 @Autowired private ObjectMapper objectMapper; @Autowired //咱们本身的配置 private GarySecurityProperties garySecurityProperties; @Override //登录不成功产生的错误 public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { System.out.println("登录失败"); if(LoginType.JSON.equals(garySecurityProperties.getLoginType())) { //设置返回的状态码 500 SC_INTERNAL_SERVER_ERROR response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR); response.setContentType("application/json;charset=UTF-8"); //将咱们authentication转换为json经过response对象以application/json写到页面 response.getWriter().write(objectMapper.writeValueAsString(exception)); } else { //调用父类中的方法,跳转到其它页面 super.onAuthenticationFailure(request, response, exception); } } }