SpringBoot SpringSecurity 介紹(基於記憶體的驗證)

2023-04-28 12:01:36

SpringBoot 整合 SpringSecurity + MySQL + JWT 附原始碼,廢話不多直接盤
SpringBoot已經為使用者採用預設設定,只需要引入pom依賴就能快速啟動Spring Security。
目的:驗證請求使用者的身份,提供安全存取
優勢:基於Spring,設定方便,減少大量程式碼

內建存取控制方法

  • permitAll() 表示所匹配的 URL 任何人都允許存取。
  • authenticated() 表示所匹配的 URL 都需要被認證才能存取。
  • anonymous() 表示可以匿名存取匹配的 URL 。和 permitAll() 效果類似,只是設定為 anonymous() 的 url 會執行 filter 鏈中
  • denyAll() 表示所匹配的 URL 都不允許被存取。
  • rememberMe() 被「remember me」的使用者允許存取 這個有點類似於很多網站的十天內免登入,登陸一次即可記住你,然後未來一段時間不用登入。
  • fullyAuthenticated() 如果使用者不是被 remember me 的,才可以存取。也就是必須一步一步按部就班的登入才行。

角色許可權判斷

  • hasAuthority(String) 判斷使用者是否具有特定的許可權,使用者的許可權是在自定義登入邏輯
  • hasAnyAuthority(String ...) 如果使用者具備給定許可權中某一個,就允許存取
  • hasRole(String) 如果使用者具備給定角色就允許存取。否則出現 403
  • hasAnyRole(String ...) 如果使用者具備給定角色的任意一個,就允許被存取
  • hasIpAddress(String) 如果請求是指定的 IP 就執行存取。可以通過 request.getRemoteAddr() 獲取 ip 地址

參照 Spring Security

Pom 檔案中新增

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>
點選檢視POM程式碼
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>vipsoft-parent</artifactId>
        <groupId>com.vipsoft.boot</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>vipsoft-security</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
  
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.3.7</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

執行後會自動生成 password 預設使用者名稱為: user

預設設定每次都啟動專案都會重新生成密碼,同時使用者名稱和攔截請求也不能自定義,在實際應用中往往需要自定義設定,因此接下來對Spring Security進行自定義設定。

設定 Spring Security (入門)

在記憶體中(簡化環節,瞭解邏輯)設定兩個使用者角色(admin和user),設定不同密碼;
同時設定角色存取許可權,其中admin可以存取所有路徑(即/*),user只能存取/user下的所有路徑。

自定義設定類,實現WebSecurityConfigurerAdapter介面,WebSecurityConfigurerAdapter介面中有兩個用到的 configure()方法,其中一個設定使用者身份,另一個設定使用者許可權:

設定使用者身份的configure()方法:

SecurityConfig

package com.vipsoft.web.config;

import org.springframework.context.annotation.Configuration;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 設定使用者身份的configure()方法
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        //簡化操作,將使用者名稱和密碼存在記憶體中,後期會存放在資料庫、Redis中
        auth.inMemoryAuthentication()
                .passwordEncoder(passwordEncoder)
                .withUser("admin")
                .password(passwordEncoder.encode("888"))
                .roles("ADMIN")
                .and()
                .withUser("user")
                .password(passwordEncoder.encode("666"))
                .roles("USER");
    }

    /**
     * 設定使用者許可權的configure()方法
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //設定攔截的路徑、設定哪類角色可以存取該路徑
                .antMatchers("/user").hasAnyRole("USER")
                .antMatchers("/*").hasAnyRole("ADMIN")
                //設定登入介面,可以新增自定義介面, 沒新增則用系統預設的介面
                .and().formLogin();

    }
}

新增介面測試用


package com.vipsoft.web.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DefaultController {

    @GetMapping("/")
    @PreAuthorize("hasRole('ADMIN')")
    public String demo() {
        return "Welcome";
    }

    @GetMapping("/user/list")
    @PreAuthorize("hasAnyRole('ADMIN','USER')")
    public String getUserList() {
        return "User List";
    }

    @GetMapping("/article/list")
    @PreAuthorize("hasRole('ADMIN')")
    public String getArticleList() {
        return "Article List";
    }
}