<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Spring Security 快速上手

      Spring Security 框架簡介

      Spring Security 說明

      • Spring Security 基于 Spring 框架,提供了一套 Web 應用安全性的完整解決方案
        1. 關于安全方面的兩個主要區域是“認證”和“授權”(或者訪問控制),一般來說,Web 應用的安全性包括用戶認證(Authentication)和用戶授權(Authorization)兩個部分,這兩點也是 Spring Security 重要核心功能。
          1. 用戶認證:驗證某個用戶是否為系統中的合法主體,也就是說用戶能否訪問該系統。用戶認證一般要求用戶提供用戶名和密碼。系統通過校驗用戶名和密碼來完成認證過程。通俗點說就是系統認為用戶是否能登錄。
          2. 用戶授權:驗證某個用戶是否有權限執行某個操作。在一個系統中,不同用戶所具有的權限是不同的。比如對一個文件來說,有的用戶只能進行讀取,而有的用戶可以進行修改。一般來說,系統會為不同的用戶分配不同的角色,而每個角色則對應一系列的權限。通俗點講就是系統判斷用戶是否有權限去做某些事情。

      Spring Security 官網

      Spring Security 特點

      1. 和 Spring 無縫整合
      2. 重量級、全面的權限控制
      3. 專門為 Web 開發而設計
        1. 舊版本不能脫離 Web 環境使用。
        2. 新版本對整個框架進行了分層抽取,分成了核心模塊和 Web 模塊。單獨引入核心模塊就可以脫離 Web 環境。

      Spring Security 對比 Shiro

      Shiro 簡介

      • Shrio 是Apache 旗下的輕量級權限控制框架

        特點:

        1. 輕量級。Shiro 主張的理念是把復雜的事情變簡單。針對對性能有更高要求的互聯網應用有更好表現。
        2. 通用性:
          1. 好處:不局限于 Web 環境,可以脫離 Web 環境使用。
          2. 缺陷:在 Web 環境下一些特定的需求需要手動編寫代碼定制。

      總結

      Spring Security 是 Spring 家族中的一個安全管理框架,實際上,在 Spring Boot 出現之前,Spring Security 就已經發展了多年了,但是使用的并不多,安全管理這個領域,一直是 Shiro 的天下。

      相對于 Shiro,在 SSM 中整合 Spring Security 都是比較麻煩的操作,所以,SpringSecurity 雖然功能比 Shiro 強大,但是使用反而沒有 Shiro 多(Shiro 雖然功能沒有Spring Security 多,但是對于大部分項目而言,Shiro 也夠用了)。

      自從有了 Spring Boot 之后,Spring Boot 對于 Spring Security 提供了自動化配置方案,可以使用更少的配置來使用 Spring Security。

      因此,一般來說,常見的安全管理技術棧的組合是這樣的:

      ? SSM + Shiro
      ? Spring Boot/Spring Cloud + Spring Security

      以上只是一個推薦的組合而已,如果單純從技術上來說,無論怎么組合,都是可以運行的。

      Spring Security 框架快速入門

      1. 搭建spring boot 項目,并引入項目依賴

         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        
      2. 新建Controller,并配置訪問方法

        package org.taoguoguo.controller;
        
        import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.RequestMapping;
        import org.springframework.web.bind.annotation.RestController;
        
        /**
         * @author taoGuoGuo
         * @description HelloController
         * @website http://www.rzrgm.cn/doondo
         * @create 2021-06-11 14:16
         */
        @RestController
        @RequestMapping("/test")
        public class HelloController {
        
            @GetMapping("hello")
            public String hello(){
                return "hello security";
            }
        }
        
      3. 訪問對應的方法,我們發現跳轉至了默認的Spring Security 登錄頁面,用戶名默認為 user , 密碼為 控制臺打印 password

        Using generated security password: 22f1f943-b70b-43e9-bf56-adf37851a9e7

      Spring Security 用戶名密碼配置

      剛剛我們的密碼是在控制臺,Spring Security 內置實現的密碼登錄,那實際工作中我們怎么自己指定用戶名密碼呢?

      常見的方式有三種:

      1. 通過配置文件指定
      2. 通過配置類指定
      3. 通過實現 UserDetailService 接口實現 數據庫查詢

      通過配置文件指定

      在 application.properties 中 進行配置

      #第一種方式:通過配置文件配置Spring Security用戶名密碼
      spring.security.user.name=taoguoguo
      spring.security.user.password=taoguoguo
      

      通過配置類實現 配置用戶名密碼

      新建 SecurityConfig 并 實現 WebSecurityConfigurerAdapter 適配器實現配置重寫

      package org.taoguoguo.config;
      
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
      import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
      import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
      import org.springframework.security.crypto.password.PasswordEncoder;
      
      /**
       * @author taoGuoGuo
       * @description SecurityConfig
       * @website http://www.rzrgm.cn/doondo
       * @create 2021-06-11 14:55
       */
      @Configuration
      public class SecurityConfig extends WebSecurityConfigurerAdapter {
      
          //如果缺少密碼解析 登陸后會返回當前登陸頁面 并報 id 為 null 的錯誤
          @Bean
          PasswordEncoder passwordEncoder(){
              return new BCryptPasswordEncoder();
          }
      
          //方式二:通過配置類設置登錄用戶名和密碼,通過auth設置用戶名密碼
          @Override
          protected void configure(AuthenticationManagerBuilder auth) throws Exception {
              BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
              String password = passwordEncoder.encode("taoguoguo");
              auth.inMemoryAuthentication().withUser("taoguoguo").password(password).roles("admin");
          }
      }
      
      

      通過實現 UserDetailService 自定義實現

      自定義實現類配置:

      1. 創建配置類,設置使用哪個userDetailService 實現類

        package org.taoguoguo.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.authentication.builders.AuthenticationManagerBuilder;
        import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
        import org.springframework.security.core.userdetails.UserDetailsService;
        import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
        import org.springframework.security.crypto.password.PasswordEncoder;
        
        /**
         * @author taoGuoGuo
         * @description SecurityConfig
         * @website http://www.rzrgm.cn/doondo
         * @create 2021-06-11 15:14
         * SpringSecurity 自定義配置
         */
        @Configuration
        public class SecurityConfig  extends WebSecurityConfigurerAdapter {
        
            @Autowired
            private UserDetailsService userDetailsService;
        
            @Override
            protected void configure(AuthenticationManagerBuilder auth) throws Exception {
                //設置自定義的數據庫實現及密碼解析器
                auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
            }
        
            @Bean
            PasswordEncoder passwordEncoder(){
                return new BCryptPasswordEncoder();
            }
        }
        
        
      2. 編寫實現類,返回User對象,User對象有用戶名密碼和操作權限

        package org.taoguoguo.service;
        
        import org.springframework.security.core.GrantedAuthority;
        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.bcrypt.BCryptPasswordEncoder;
        import org.springframework.stereotype.Service;
        
        import java.util.List;
        
        /**
         * @author taoGuoGuo
         * @description MyUserDetailService
         * @website http://www.rzrgm.cn/doondo
         * @create 2021-06-11 15:18
         */
        @Service("userDetailsService")
        public class MyUserDetailService implements UserDetailsService {
        
            /**
             * 自定義實現類方式查詢用戶名密碼
             * @param s
             * @return
             * @throws UsernameNotFoundException
             */
            @Override
            public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
                BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
                //密碼
                String password = passwordEncoder.encode("taoguoguo");
                //權限
                List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
                return new User("taoguoguo", password, auths);
            }
        }
        

      數據庫查詢認證

      1. 數據庫建立 users表

        CREATE TABLE `users` (
          `id` bigint(20) NOT NULL AUTO_INCREMENT,
          `username` varchar(20) COLLATE utf8mb4_general_ci NOT NULL,
          `password` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL,
          PRIMARY KEY (`id`),
          UNIQUE KEY `username` (`username`)
        ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
        
      2. 項目添加依賴 采用 mybatis-plus

        <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
            <modelVersion>4.0.0</modelVersion>
            <parent>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>2.5.1</version>
                <relativePath/> <!-- lookup parent from repository -->
            </parent>
            <groupId>org.taoguoguo</groupId>
            <artifactId>spring-security</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <name>spring-security</name>
            <description>Demo project for Spring Boot</description>
            <properties>
                <java.version>1.8</java.version>
            </properties>
        
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-web</artifactId>
                </dependency>
        
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-security</artifactId>
                </dependency>
        
                <dependency>
                    <groupId>com.baomidou</groupId>
                    <artifactId>mybatis-plus-boot-starter</artifactId>
                    <version>3.4.3</version>
                </dependency>
        
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                </dependency>
        
                <dependency>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                </dependency>
        
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-test</artifactId>
                    <scope>test</scope>
                </dependency>
        
            </dependencies>
        
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
        
        </project>
        
        
      3. 增加數據庫參數配置

        server.port=8111
        
        #數據庫配置
        spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
        spring.datasource.url=jdbc:mysql://localhost:3306/security_db?serverTimezone=GMT%2B8
        spring.datasource.username=root
        spring.datasource.password=root
        
      4. 創建Users實體

        package org.taoguoguo.entity;
        
        import lombok.Data;
        
        /**
         * @author taoGuoGuo
         * @description Users
         * @website http://www.rzrgm.cn/doondo
         * @create 2021-06-11 15:51
         */
        @Data
        public class Users {
            private Integer id;
            private String username;
            private String password;
        }
        
        
      5. 創建UsersMapper

        package org.taoguoguo.mapper;
        
        import com.baomidou.mybatisplus.core.mapper.BaseMapper;
        import org.springframework.stereotype.Repository;
        import org.taoguoguo.entity.Users;
        
        /**
         * @author taoGuoGuo
         * @description UsersMapper
         * @website http://www.rzrgm.cn/doondo
         * @create 2021-06-11 15:53
         */
        @Repository
        public interface UsersMapper extends BaseMapper<Users> {
        }
        
        
      6. 修改自定義配置實現類 MyUserDetailService 進行數據庫查詢

        package org.taoguoguo.service;
        
        import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.security.core.GrantedAuthority;
        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.stereotype.Service;
        import org.taoguoguo.entity.Users;
        import org.taoguoguo.mapper.UsersMapper;
        import java.util.List;
        
        /**
         * @author taoGuoGuo
         * @description MyUserDetailService
         * @website http://www.rzrgm.cn/doondo
         * @create 2021-06-11 15:18
         */
        @Service("userDetailsService")
        public class MyUserDetailService implements UserDetailsService {
        
            @Autowired
            private UsersMapper usersMapper;
            /**
             * 自定義實現類方式查詢用戶名密碼
             * @param username
             * @return
             * @throws UsernameNotFoundException
             */
            @Override
            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                //調用usersMapper方法,根據用戶名查詢數據庫
                QueryWrapper<Users> wrapper = new QueryWrapper<>();
                wrapper.eq("username", username);
                Users users = usersMapper.selectOne(wrapper);
                if(users == null){  //數據庫沒有該用戶名 認證失敗
                    throw new UsernameNotFoundException("用戶名或密碼不存在!");
                }
                //權限
                List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
                return new User(users.getUsername(), users.getPassword(), auths);
            }
        }
        
        
      7. 在Spring Boot 配置啟動類中進行Mapper注解掃描配置 注入Mapper Bean

        package org.taoguoguo;
        
        import org.mybatis.spring.annotation.MapperScan;
        import org.springframework.boot.SpringApplication;
        import org.springframework.boot.autoconfigure.SpringBootApplication;
        
        @SpringBootApplication
        @MapperScan("org.taoguoguo.mapper")
        public class SpringSecurityApplication {
            public static void main(String[] args) {
                SpringApplication.run(SpringSecurityApplication.class, args);
            }
        
        }
        

      Spring Security自定義登錄頁面 及 認證放行

      通過重寫 webSecurityConfigureAdapter 的 configure(HttpSecurity http) 方法進行配置

      @Override
          protected void configure(HttpSecurity http) throws Exception {
              http.formLogin()    //自定義自己編寫登錄頁面
                      .loginPage("/login.html")           //登錄頁面設置
                      .loginProcessingUrl("/user/login")  //登錄訪問路徑
                      .defaultSuccessUrl("/test/index")   //登錄成功后,跳轉路徑
                      .permitAll()
                      .and().authorizeRequests()  //定義請求路徑訪問規則
                      .antMatchers("/","/test/hello","/user/login").permitAll() //設置不需要認證可以直接訪問的路徑
                      .anyRequest().authenticated()   //除此之外任何請求都需要認證
                      .and().csrf().disable();    //關閉csrf防護
          }
      

      基于角色或權限的進行訪問控制

      • hasAuthority 方法,主要針對某一個權限進行控制訪問

        如果當前的主體具有指定的權限,則返回 true,否則返回 false

        修改配置類,增加.antMatchers("/test/index").hasAuthority("admin") 具備admin權限 才能訪問 /test/index路徑

        @Override
            protected void configure(HttpSecurity http) throws Exception {
                http.formLogin()    //自定義自己編寫登錄頁面
                        .loginPage("/login.html")           //登錄頁面設置
                        .loginProcessingUrl("/user/login")  //登錄訪問路徑
                        .defaultSuccessUrl("/test/index")   //登錄成功后,跳轉路徑
                        .permitAll()
                        .and().authorizeRequests()  //定義請求路徑訪問規則
                        .antMatchers("/","/test/hello","/user/login").permitAll() //設置不需要認證可以直接訪問的路徑
                        .antMatchers("/test/index").hasAuthority("admin")   //具備admin權限才能訪問 /test/index資源
                        .anyRequest().authenticated()   //除此之外任何請求都需要認證
                        .and().csrf().disable();    //關閉csrf防護
            }
        

        那這個admin的權限是在哪里指定的呢?其實在之前我們已經提到過,在自定義的登錄邏輯中,我們會放置用戶所具備的權限信息

        List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");

        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //調用usersMapper方法,根據用戶名查詢數據庫
            QueryWrapper<Users> wrapper = new QueryWrapper<>();
            wrapper.eq("username", username);
            Users users = usersMapper.selectOne(wrapper);
            if(users == null){  //數據庫沒有該用戶名 認證失敗
                throw new UsernameNotFoundException("用戶名或密碼不存在!");
            }
            //權限
            List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
            return new User(users.getUsername(), users.getPassword(), auths);
        }
        
      • hasAnyAuthority 方法

        如果當前的主體有任何提供的角色(給定的作為一個逗號分隔的字符串列表)的話,返回true

        修改配置類,增加.antMatchers("/test/index").hasAnyAuthority("admin,manager") 具備admin 或 manager其中任一權限 就能訪問 /test/index路徑

         @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.formLogin()    //自定義自己編寫登錄頁面
                .loginPage("/login.html")           //登錄頁面設置
                .loginProcessingUrl("/user/login")  //登錄訪問路徑
                .defaultSuccessUrl("/test/index")   //登錄成功后,跳轉路徑
                .permitAll()
                .and().authorizeRequests()  //定義請求路徑訪問規則
                .antMatchers("/","/test/hello","/user/login").permitAll() //設置不需要認證可以直接訪問的路徑
                .antMatchers("/test/index").hasAnyAuthority("admin,manager")
                .anyRequest().authenticated()   //除此之外任何請求都需要認證
                .and().csrf().disable();    //關閉csrf防護
        }
        
      • hasRole 如果用戶具備給定角色就允許訪問,否則出現 403 如果當前主體具有指定的角色,則返回 true。

        查看源碼用法

        // hasRole 取出角色相關信息 access 判斷是否能夠訪問
        public ExpressionInterceptUrlRegistry hasRole(String role) {
            return access(ExpressionUrlAuthorizationConfigurer.hasRole(role));
        }
        
        // 為role 底層拼接 ROLE_ 所以 我們在自定義登錄邏輯 賦予權限時 要拼接 ROLE_
        private static String hasRole(String role) {
            Assert.notNull(role, "role cannot be null");
            Assert.isTrue(!role.startsWith("ROLE_"),
                          () -> "role should not start with 'ROLE_' since it is automatically inserted. Got '" + role + "'");
            return "hasRole('ROLE_" + role + "')";
        }
        
        

        修改配置類,配置用戶具備 deptManager才能訪問 /test/index資源

         @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.formLogin()    //自定義自己編寫登錄頁面
                .loginPage("/login.html")           //登錄頁面設置
                .loginProcessingUrl("/user/login")  //登錄訪問路徑
                .defaultSuccessUrl("/test/index")   //登錄成功后,跳轉路徑
                .permitAll()
                .and().authorizeRequests()  //定義請求路徑訪問規則
                .antMatchers("/","/test/hello","/user/login").permitAll() //設置不需要認證可以直接訪問的路徑
                .antMatchers("/test/index").hasRole("deptManager")
                .anyRequest().authenticated()   //除此之外任何請求都需要認證
                .and().csrf().disable();    //關閉csrf防護
        }
        

        給用戶配置deptManager角色權限

         @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //調用usersMapper方法,根據用戶名查詢數據庫
            QueryWrapper<Users> wrapper = new QueryWrapper<>();
            wrapper.eq("username", username);
            Users users = usersMapper.selectOne(wrapper);
            if(users == null){  //數據庫沒有該用戶名 認證失敗
                throw new UsernameNotFoundException("用戶名或密碼不存在!");
            }
            //權限
            List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("manager,ROLE_deptManager");
            return new User(users.getUsername(), users.getPassword(), auths);
        }
        
      • hasAnyRole 表示用戶具備任何一個條件都可以訪問

        用法和配置和 hasRole 一致,只不過在配置類中配置多個角色方可訪問資源路徑,同時給用戶角色信息時,給一個或多個即可

      Spring Security 自定義403 無權限訪問頁面

      1. 我們在項目的靜態資源文件夾 static 下 新建 unauth.html 自定義的403頁面

        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>自定義403頁面</title>
        </head>
        <body>
        自定義403頁面!
        </body>
        </html>
        
      2. 修改訪問配置類

        http.exceptionHandling().accessDeniedPage("/unauth");
        

      Spring Security 注解使用

      @Secured 判斷是否具有角色

      1. 開啟Spring Security注解功能 @EnableGlobalMethodSecurity(securedEnabled = true)

        package org.taoguoguo;
        
        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;
        
        @SpringBootApplication
        @MapperScan("org.taoguoguo.mapper")
        @EnableGlobalMethodSecurity(securedEnabled = true)
        public class SpringSecurityApplication {
            public static void main(String[] args) {
                SpringApplication.run(SpringSecurityApplication.class, args);
            }
        
        }
        
        
      2. 編寫需要 Secured 注解指定角色訪問的控制器

        @GetMapping("testSecured")
        @Secured({"ROLE_sale","ROLE_admin"})
        public String testSecured(){
            return "hello Secured";
        }
        
      3. 在自定義登錄邏輯中,為用戶分配對應的角色信息

        List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("manager,ROLE_sale");

      @PreAuthorize 進入方法前的權限驗證

      1. 開啟注解功能 @EnableGlobalMethodSecurity(prePostEnabled = true)

        package org.taoguoguo;
        
        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;
        
        @SpringBootApplication
        @MapperScan("org.taoguoguo.mapper")
        @EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
        public class SpringSecurityApplication {
            public static void main(String[] args) {
                SpringApplication.run(SpringSecurityApplication.class, args);
            }
        
        }
        
        
      2. 編寫需要 preAuthorize 需要權限驗證的控制器

        @RequestMapping("/preAuthorize")
        @PreAuthorize("hasAuthority('menu:system')")
        public String preAuthorize(){
            return "Hello preAuthorize";
        }
        
      3. 在自定義登錄邏輯中,為用戶分配對應的角色信息

        List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("manager,menu:system,menu:create");

      @PostAuthorize 在方法執行后再進行權限驗證,適合驗證帶有返回值的權限

      用法和 preAuthorize 基本一致,比較簡單,這邊就不詳細說明了。重點明白什么場景下使用即可

      @PostFilter 權限驗證之后對數據進行過濾

      留下用戶名是 admin1 的數據 表達式中的 filterObject 引用的是方法返回值 List 中的某一個元素

      @RequestMapping("getAll")
      @PreAuthorize("hasRole('ROLE_ 管理員')")
      @PostFilter("filterObject.username == 'admin1'")
      @ResponseBody
      public List<UserInfo> getAllUser(){
      ArrayList<UserInfo> list = new ArrayList<>();
      list.add(new UserInfo(1l,"admin1","6666"));
      list.add(new UserInfo(2l,"admin2","888"));
      return list;
      }
      

      @PreFilter 進入控制器之前對數據進行過濾

      留下傳入參數 id 能對 2 整除的參數數據

      @RequestMapping("getTestPreFilter")
      @PreAuthorize("hasRole('ROLE_ 管理員')")
      @PreFilter(value = "filterObject.id%2==0")
      @ResponseBody
      public  List<UserInfo>  getTestPreFilter(@RequestBody  List<UserInfo> list){
          list.forEach(t-> {
              System.out.println(t.getId()+"\t"+t.getUsername());
          });
          return list;
      }
      

      Spring Security 實現 RememberMe

      用戶流程及框架實現原理

      具體實現方式

      1. 創建表,這個表也可以由程序自動創建

        CREATE TABLE `persistent_logins` (
          `username` varchar(64) NOT NULL,
          `series` varchar(64) NOT NULL,
          `token` varchar(64) NOT NULL,
          `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
          PRIMARY KEY (`series`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
        
      2. 添加數據庫配置文件

        #數據庫配置
        spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
        spring.datasource.url=jdbc:mysql://localhost:3306/security_db?serverTimezone=GMT%2B8
        spring.datasource.username=root
        spring.datasource.password=root
        
      3. 修改配置類 SecurityConfig 中 注入數據源及配置數據庫操作對象

        //注入數據源
        @Autowired
        private DataSource dataSource;
        
        //注入數據源 配置操作數據庫對象
        @Bean
        public PersistentTokenRepository persistentTokenRepository(){
            JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
            jdbcTokenRepository.setDataSource(dataSource);
            //jdbcTokenRepository.setCreateTableOnStartup(true);  //配置此配置則會自動幫我們建表
            return jdbcTokenRepository;
        }
        
      4. 開啟 Remeber me 功能

        //開啟記住我功能
        http.rememberMe().tokenRepository(persistentTokenRepository())
            .tokenValiditySeconds(60*15)    //有效時長 15分鐘
            .userDetailsService(userDetailsService);
        
      5. login.html 頁面增加記住我 功能標簽 【注意:name 屬性值必須位 remember-me.不能改為其他值】

        <form action="/user/login" method="post">
            用戶名:<input type="text" name="username"><br/>
            密 碼:<input type="password" name="password"><br/>
            <input type="checkbox" name="remember-me" title="記住密碼">自動登錄<br/>
            <input type="submit" value="login">
        </form>
        

      最后附上完整的配置類代碼

      package org.taoguoguo.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.authentication.builders.AuthenticationManagerBuilder;
      import org.springframework.security.config.annotation.web.builders.HttpSecurity;
      import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
      import org.springframework.security.core.userdetails.UserDetailsService;
      import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
      import org.springframework.security.crypto.password.PasswordEncoder;
      import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
      import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
      
      import javax.sql.DataSource;
      
      /**
       * @author taoGuoGuo
       * @description SecurityConfig
       * @website http://www.rzrgm.cn/doondo
       * @create 2021-06-11 15:14
       * SpringSecurity 自定義配置
       */
      @Configuration
      public class SecurityConfig  extends WebSecurityConfigurerAdapter {
      
          @Autowired
          private UserDetailsService userDetailsService;
      
          //注入數據源
          @Autowired
          private DataSource dataSource;
      
          //注入數據源 配置操作數據庫對象
          @Bean
          public PersistentTokenRepository persistentTokenRepository(){
              JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
              jdbcTokenRepository.setDataSource(dataSource);
              //jdbcTokenRepository.setCreateTableOnStartup(true);  //配置此配置則會自動幫我們建表
              return jdbcTokenRepository;
          }
      
      
          @Override
          protected void configure(AuthenticationManagerBuilder auth) throws Exception {
              //設置自定義的數據庫實現及密碼解析器
              auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
          }
      
      
          @Override
          protected void configure(HttpSecurity http) throws Exception {
              //表單認證
              http.formLogin()    //自定義自己編寫登錄頁面
                      .loginPage("/login.html")           //登錄頁面設置
                      .loginProcessingUrl("/user/login")  //登錄訪問路徑
                      .defaultSuccessUrl("/sys/loginSuccess")   //登錄成功后,跳轉路徑
                      .permitAll()
                      .and().authorizeRequests()  //定義請求路徑訪問規則
                      .antMatchers("/","/test/hello","/user/login").permitAll() //設置不需要認證可以直接訪問的路徑
                      //1 hasAuthority方法 具備admin權限才能訪問 /test/index資源
                      // .antMatchers("/test/index").hasAuthority("admin")
                      //2 hasAnyAuthority方法 具備admin,manager其中任一權限 才能訪問/test/index資源
                      // .antMatchers("/test/index").hasAnyAuthority("admin,manager")
                      .antMatchers("/test/index").hasRole("manager")
                      .anyRequest().authenticated();   //除此之外任何請求都需要認證
      
              //開啟記住我功能
              http.rememberMe().tokenRepository(persistentTokenRepository())
                      .tokenValiditySeconds(60*15)    //有效時長 15分鐘
                      .userDetailsService(userDetailsService);
      
              //關閉csrf防護
              http.csrf().disable();
              //用戶注銷配置
              http.logout().logoutUrl("/logout").logoutSuccessUrl("/sys/logout").permitAll();
              //自定義403頁面
              http.exceptionHandling().accessDeniedPage("/sys/unauth403");
          }
      
          @Bean
          PasswordEncoder passwordEncoder(){
              return new BCryptPasswordEncoder();
          }
      }
      
      
      posted @ 2021-06-16 17:26  DOONDO  閱讀(384)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 亚洲熟女乱色一区二区三区| 亚洲综合伊人久久综合| 毛多水多高潮高清视频| 中文无码热在线视频| 国产成人综合95精品视频| 男受被做哭激烈娇喘gv视频| 免费看欧美日韩一区二区三区| 日本五十路熟女一区二区| 国产91丝袜在线播放动漫| 日韩一区二区三区日韩精品| 在线a级毛片无码免费真人| 无码人妻丰满熟妇区bbbbxxxx | 色香欲天天影视综合网| 中国亚洲女人69内射少妇 | 狠狠色狠狠综合久久| 色婷婷综合久久久中文字幕| 国产在线视频www色| 性欧美vr高清极品| 亚洲高清有码中文字| 亚洲综合网一区中文字幕| 亚洲午夜香蕉久久精品| 小污女小欲女导航| 69精品丰满人妻无码视频a片| a级国产乱理伦片在线观看al| 精品少妇人妻av无码久久| 亚洲国产欧美在线看片一国产| 国产精品一区二区三区四区| 国产成AV人片久青草影院| 强奷乱码欧妇女中文字幕熟女| 亚洲男人天堂东京热加勒比| 国产精品午夜精品福利| 久久a级片| 亚洲线精品一区二区三八戒| 久久这里只有精品好国产| 午夜免费福利小电影| 欧美成人黄在线观看| 高清精品视频一区二区三区| 欧美亚洲另类制服卡通动漫| 国产v综合v亚洲欧美大天堂| 久热色精品在线观看视频| 成人精品天堂一区二区三区|