SpringBoot 2整合SpringSecurity權限管理(一)SpringSecurity介紹及簡單搭建

本系列文章參考了大量文獻資料,如楊傳傑博客江南一點雨等,感謝原作者。

本文默認版本:SpringBoot 2.1.9

概述

Spring Security 是 Spring 社區的一個頂級項目,也是 Spring Boot 官方推薦使用的安全框架。除了常規的認證(Authentication)和授權(Authorization)之外,Spring Security還提供了諸如ACLs,LDAP,JAAS,CAS等高級特性以滿足複雜場景下的安全需求。另外,就目前而言,Spring Security和Shiro也是當前廣大應用使用比較廣泛的兩個安全框架。

Spring Security 應用級別的安全主要包含兩個主要部分,即登錄認證(Authentication)和訪問授權(Authorization),首先用戶登錄的時候傳入登錄信息,登錄驗證器完成登錄認證並將登錄認證好的信息存儲到請求上下文,然後再進行其他操作,如在進行接口訪問、方法調用時,權限認證器從上下文中獲取登錄認證信息,然後根據認證信息獲取權限信息,通過權限信息和特定的授權策略決定是否授權。

實際上,在 Spring Boot 出現之前,Spring Security 就已經發展了多年了,但是使用的並不多,安全管理這個領域,一直是 Shiro 的天下。相對於 Shiro,在 SSM/SSH 中整合 Spring Security 都是比較麻煩的操作,所以,Spring Security 雖然功能比 Shiro 強大,但是使用反而沒有 Shiro 多(Shiro 雖然功能沒有 Spring Security 多,但是對於大部分項目而言,Shiro 也夠用了)。

自從有了 Spring Boot 之後,Spring Boot 對於 Spring Security 提供了 自動化配置方案,可以零配置使用 Spring Security。

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

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

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

一、創建一個SpringBoot項目,引入SpringSecurity依賴

  1. pom.xml 中的 Spring Security 依賴:
<!-- spring security -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

​ 只要加入依賴,項目的所有接口都會被自動保護起來。

注意:引入spring security依賴時,會自動啓動spring security
禁用:@SpringBootApplication(exclude = {SecurityAutoConfiguration.class })

  1. 我們創建一個 HelloController:

    /**
     * @author ZHANGCHAO
     * @date 2020/3/11 10:34
     * @since 1.0.0
     */
    @RestController
    public class MainController {
        @GetMapping("/hello")
        public String login() {
            return "Hello World";
        }
    }
    
    

    啓動項目–觀察控制檯

    20190709165723610

    默認情況下,登錄的用戶名是 user ,密碼則是項目啓動時隨機生成的字符串,可以從啓動的控制檯日誌中看到默認密碼。

    訪問 /hello ,會看到spring security使用了默認登錄頁面,默認用戶user,密碼就是上面的,輸入用戶密碼成功訪問。

    25-2

    當用戶從瀏覽器發送請求訪問 /hello 接口時,服務端會返回 302 響應碼,讓客戶端重定向到 /login 頁面,用戶在 /login 頁面登錄,登陸成功之後,就會自動跳轉到 /hello 接口。

    另外,也可以使用 POSTMAN 來發送請求,使用 POSTMAN 發送請求時,可以將用戶信息放在請求頭中(這樣可以避免重定向到登錄頁面):

    25-3

通過以上兩種不同的登錄方式,可以看出,Spring Security 支持兩種不同的認證方式:

  • 可以通過 form 表單來認證
  • 可以通過 HttpBasic 來認證

二、自定義登錄用戶和密碼

隨機生成的密碼,每次啓動時都會變。對登錄的用戶名/密碼進行配置,有三種不同的方式:

  • 在 application.properties 中進行配置
  • 通過 Java 代碼配置在內存中
  • 通過 Java 從數據庫中加載
  1. 直接在 application.properties 文件中配置用戶的基本信息:

    ## Spring Security配置
    spring.security.user.name=admin
    spring.security.user.password=666666
    

    配置完成後,重啓項目,就可以使用這裏配置的用戶名/密碼登錄了。

  2. 在 Java 代碼中配置用戶名密碼,首先需要我們創建一個 Spring Security 的配置類,集成自 WebSecurityConfigurerAdapter 類,如下:

    @Slf4j
    @EnableWebSecurity //開啓web security配置 這是一個組合註解
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        /**
         * spring5.0之後,spring security必須設置加密方法否則會報
         * There is no PasswordEncoder mapped for the id "null"
         * @return 加密
         */
        @Bean
        public BCryptPasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder(4);
        }
        
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests() //需要授權的請求
                    .anyRequest().authenticated() //對任何一個請求,都需要認證
                    .and() //完成上一個配置,進行下一步配置
                    .httpBasic(); //開啓httpBasic登錄
        }
    }
    

    從 Spring5 開始,強制要求密碼要加密,如果非不想加密,可以使用一個過期的 PasswordEncoder 的實例 NoOpPasswordEncoder,但是不建議這麼做,畢竟不安全。

  3. 配置AuthenticationManager

    有兩種方式:

    (1) 重寫configure(AuthenticationManagerBuilder auth)

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
    }
    

    (2) 注入 configureGlobal(AuthenticationManagerBuilder auth)

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {}
    

    說明: configureGlobal可以跨多個WebSecurityConfigurerAdapter;configure只能只能作用一個!

    如果你的應用只有唯一一個WebSecurityConfigurerAdapter,那麼他們之間的差距可以被忽略,從方法名可以看出兩者的區別:使用@Autowired注入的AuthenticationManagerBuilder是全局的身份認證器,作用域可以跨越多個WebSecurityConfigurerAdapter,以及影響到基於Method的安全控制;而 protected configure()的方式則類似於一個匿名內部類,它的作用域侷限於一個WebSecurityConfigurerAdapter內部。

    最後啓動應用,輸入admin,666666成功通過驗證。

三、自定義登錄頁面和退出頁面

  1. 配置WebMvcConfig

    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
    
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/home").setViewName("home");
            registry.addViewController("/main").setViewName("main");
            registry.addViewController("/").setViewName("home");
            registry.addViewController("/hello").setViewName("hello");
            registry.addViewController("/login").setViewName("login");
            
        }
    

    當項目中涉及大量的頁面跳轉,我們可以使用addViewControllers方法實現無業務邏輯跳轉,從而減少控制器代碼的編寫。

    addViewControllers方法可以實現將一個請求直接映射爲視圖,不需要編寫控制器來實現,從而簡化了頁面跳轉。

  2. 在SecurityConfig中配置HttpSecurity

     @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests() //需要授權的請求
                    .antMatchers("/login","/home").permitAll() //過濾不需要認證的路徑
                    .anyRequest().authenticated() //對任何一個請求,都需要認證
                    .and() //完成上一個配置,進行下一步配置
                    //.httpBasic();
                    .formLogin() //配置表單登錄
                    .loginPage("/login") //設置登錄頁面
                    .and()
                    .logout() //登出
                    .logoutSuccessUrl("/home"); //設置退出頁面
        }
    
  3. 在resources下新建目錄templates,新建幾個頁面

    33333

四、簡單搭建完成,啓動測試

11111

222223

PS 願你一生努力,一生被愛,想要的都擁有,得不到的都釋懷,更多幹貨,請來我的個人主頁

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章