系列博文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); } } }