1.前言
仍然是使用cookie存儲登錄數據,但是存儲的數據 由 spring security自動創建 ,當登出后自動刪除cookie,
如果不登出也仍在生命周期內,關閉瀏覽器再打開將會自動登錄,無需手動再登錄。
2.操作
需要在設置有spring security 的spring boot 工程基礎上【詳細可查看我的其他隨筆,有詳細記載,具體操作這里不解釋】加上下面配置
(1)
security 配置里有兩種寫法 【但是只能選擇一種】
方法一: 使用注解風格的Java配置
完整的security配置

package com.example.security5500.securityConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.stereotype.Component; //這個加不加無所謂 @Configuration //開啟security自定義配置 @EnableWebSecurity //開啟 Controller層的訪問方法權限,與注解@PreAuthorize("hasRole('ROLE_admin')")配合,會攔截注解了@PreAuthrize注解的配置 // 想要@PreAuthorize正確執行 ,權限關鍵字必須帶前綴 ROLE_ ,后面的部分可以隨便寫!!!!靠,琢磨了4小時了 ,終於找到原因了 @EnableGlobalMethodSecurity(prePostEnabled = true) //, securedEnabled = true public class WebSecurityConfig extends WebSecurityConfigurerAdapter { //實例自定義登錄校驗接口 【內部有 數據庫查詢】 @Autowired private DbUserDetailsService dbUserDetailsService; // @Bean // @Override // protected AuthenticationManager authenticationManager() throws Exception { // return super.authenticationManager(); // } //忽略攔截的靜態文件路徑 @Override public void configure(WebSecurity web) throws Exception { web.ignoring() .antMatchers( "/js/**", "/css/**", "/img/**", "/webjars/**"); } //攔截規則設置 @Override protected void configure(HttpSecurity http) throws Exception { http //允許基於使用HttpServletRequest限制訪問 //即授權請求設置 .authorizeRequests() //設置不攔截頁面,可直接通過,路徑訪問 "/", "/index", 則不攔截, .antMatchers("/", "/index", "/hhk/**") //是允許所有的意思 .permitAll() // //訪問 /hai 需要admin權限 ,無權限則提示 403 // .antMatchers("/hai").hasAuthority("admin") // //訪問 /kk 需要admin或user權限 ,無權限則提示 403 // .antMatchers("/kk").hasAnyAuthority("admin", "user") // //路徑/admin/**所有的請求都需要admin權限 ,無權限則提示 403 // .antMatchers("/admin/**").hasAuthority("admin") //其他頁面都要攔截,【需要在最后設置這個】 .anyRequest().authenticated() .and() //設置自定義登錄頁面 //即開啟登錄設置 .formLogin() //指定自定義登錄頁面的訪問虛擬路徑 .loginPage("/login") .permitAll() .and() // 添加退出登錄支持。當使用WebSecurityConfigurerAdapter時,這將自動應用。默認情況是,訪問URL”/ logout”,使HTTP Session無效 // 來清除用戶,清除已配置的任何#rememberMe()身份驗證,清除SecurityContextHolder,然后重定向到”/login?success” //即開啟登出設置 .logout() // //指定的登出操作的虛擬路徑,需要以post方式請求這個 http://localhost:5500/mylogout 才可以登出 ,也可以直接清除用戶認證信息達到登出目的 // .logoutUrl("/mylogout") //使httpsession失效 .invalidateHttpSession(true) //清除認證信息 .clearAuthentication(true) //登出請求匹配器,新建一個螞蟻路徑請求匹配器 ,與 .logoutUrl("/mylogout")效果一樣 .logoutRequestMatcher(new AntPathRequestMatcher("/mylogout")) //登出成功后訪問的地址 .logoutSuccessUrl("/home") .permitAll() .and() //開啟記住我設置,用於自動登錄 .rememberMe() //密鑰 .key("unique-and-secret") //存在cookie的用戶名[用於cookie名] .rememberMeCookieName("remember-me-cookie-name") //生命周期,單位毫秒 .tokenValiditySeconds(24 * 60 * 60); //登陸后"選擇記住我" ,會生成cookie ,登出則會自動刪除該cookie , 只要不登出且未超出生命周期 ,那么關閉瀏覽器后再次訪問將自動登錄 // [name] [value] [domain] [path] [expires/max-age] [size] [httponly] [priority] //remember-me-cookie-name eGk6MTU5MTIwODAzNDk5MTozZWUyN2FlMmEwMWQxNDczMDhhY2ZkYTAxZWQ5ZWQ5YQ localhost / 2020-06-03T18:13:54.992Z 89 ✓ Medium } /** * 添加 UserDetailsService, 實現自定義登錄校驗,數據庫查詢 */ @Override protected void configure(AuthenticationManagerBuilder builder) throws Exception { //注入用戶信息,每次登錄都會來這查詢一次信息,因此不建議每次都向mysql查詢,應該使用redis //密碼加密 builder.userDetailsService(dbUserDetailsService); // .passwordEncoder(passwordEncoder()); } /** * BCryptPasswordEncoder相關知識: * 用戶表的密碼通常使用MD5等不可逆算法加密后存儲,為防止彩虹表破解更會先使用一個特定的字符串(如域名)加密,然后再使用一個隨機的salt(鹽值)加密。 * 特定字符串是程序代碼中固定的,salt是每個密碼單獨隨機,一般給用戶表加一個字段單獨存儲,比較麻煩。 * BCrypt算法將salt隨機並混入最終加密后的密碼,驗證時也無需單獨提供之前的salt,從而無需單獨處理salt問題。 */ @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } // /** // * 選擇加密方式 ,密碼不加密的時候選擇 NoOpPasswordEncoder,不可缺少,否則報錯 // * java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null" // */ // @Bean // public static PasswordEncoder passwordEncoder() { // return NoOpPasswordEncoder.getInstance(); // } }
方法二: xml風格
xml源碼

<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <http> <!--設置不攔截的路徑--> <!-- 登錄路徑--> <intercept-url pattern="/login" access="permitAll()"/> <!-- 靜態文件路徑--> <intercept-url pattern="/js/**" access="permitAll()"/> <intercept-url pattern="/css/**" access="permitAll()"/> <intercept-url pattern="/img/**" access="permitAll()"/> <intercept-url pattern="/webjars/**" access="permitAll()"/> <!-- 設置路徑需要的指定權限 --> <intercept-url pattern="/hai" access="hasAuthority('admin')"/> <!-- 其他路徑都需要攔截認證--> <intercept-url pattern="/**" access="isAuthenticated()"/> <!--Spring Security 4.0以后默認開啟寬展請求偽造保護,這里配置禁用,不安全的操作。--> <csrf disabled="true"/> <!-- 表單登錄指定路徑--> <form-login login-page="/login"/> <!-- 登出操作--> <!-- 分別是清除session , 指定登出路徑 ,指定登出成功后路徑--> <logout invalidate-session="true" logout-url="/logout" logout-success-url="/login?logout"/> <!-- 記住我[自動登錄]設置 --> <!-- 三個參數分別是 密鑰 ,存在cookie的用戶名[用於cookie名] ,存放的生命周期[單位毫秒] --> <remember-me key="unique-and-secret" remember-me-cookie="remember-me-cookie-name" token-validity-seconds="86400"/> </http> <!-- //在內存中進行注冊公開內存的身份驗證信息 // // 在內存中添加 用戶名 ,密碼 , 權限--> <authentication-manager> <authentication-provider> <user-service> <user name="user" password="password" authorities="ROLE_USER"/> </user-service> </authentication-provider> </authentication-manager> </beans:beans>
需要在啟動類導入xml文件
package com.example.security5500; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @SpringBootApplication //設置mapper接口包位置 @MapperScan(basePackages = "com.example.security5500.dao") // // 當使用xml的方式配置時,開啟此注解,將會注釋掉WebSecurityConfig文件配置,該xml功能有同等效果 // @ImportResource("classpath:security/spring-security-config.xml") public class Security5500Application { public static void main(String[] args) { SpringApplication.run(Security5500Application.class, args); } }
使用xml 則不可以使用 注解 @EnableWebSecurity ,會導致失效
(2)在前端的自定義login.html 表單里添加“記住我”的單選框標簽 ,name屬性不可更改
完整源碼

<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"> <head> <title>Spring Security自定義</title> </head> <body> <div th:if="${param.error}"> Invalid username and password. </div> <div th:if="${param.logout}"> You have been logged out. </div> <!-- 表單的name屬性不可變 --> <form th:action="@{/login}" method="post"> <div><label> User Name : <input type="text" name="username"/> </label></div> <div><label> Password: <input type="password" name="password"/> </label></div> <div class="form-group"> <label> <input id="remember-me" name="remember-me" type="checkbox"/> 記住我 </label> </div> <div><input type="submit" value="Sign In"/></div> </form> <hr> <br> lalallalalal但是開發建設士大夫立刻 </body> </html>
3.測試
(1)啟動 ,進入登錄頁面
(2)勾選記住我登錄 ,此時cookie只有一個jsession數據
登陸后查看cookie ,多了個cookie數據
(2)關閉瀏覽器再打開該網址 ,會發現可直接進入,不需要手動輸入賬戶密碼登錄
(3)登出后,查看cookie ,會發現cookie數據沒有了,只剩下jsession