spring security 自動登錄 --- 心得


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();
//    }


}
View Code

方法二: 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>
View Code

 

需要在啟動類導入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>
View Code

 

3.測試

(1)啟動 ,進入登錄頁面

 

 

 (2)勾選記住我登錄 ,此時cookie只有一個jsession數據

 

 

 

 

 

 

 登陸后查看cookie ,多了個cookie數據

 

 (2)關閉瀏覽器再打開該網址 ,會發現可直接進入,不需要手動輸入賬戶密碼登錄  

 

(3)登出后,查看cookie ,會發現cookie數據沒有了,只剩下jsession

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM