1. 程式人生 > >SpringSecurity03 基於內存驗證

SpringSecurity03 基於內存驗證

control true tar ces post uri idea 註銷 fault

1 需求

  現有一個編寫好的系統,需要實現用戶登錄驗證即可,同時根據用戶的權限來限制用戶可以訪問的接口

2 編寫SpringSecurity配置類

  繼承 WebSecurityConfigurerAdapter 類並重寫configure 方法

  技術分享圖片

技術分享圖片
package cn.xiangxu.spring_security_system;

//import cn.xiangxu.spring_security_system.service.MyUserService;
import cn.xiangxu.spring_security_system.utils.MyPasswordEncoder;
import org.springframework.beans.factory.annotation.Autowired; 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.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** * 權限服務類 */ @Configuration
// 等同於XML中的beans @EnableWebSecurity // 開啟webSecurity功能 public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { // @Autowired // private MyUserService myUserService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 直接將用戶信息和權限寫死 auth.inMemoryAuthentication() .withUser("admin") .password("123456") .roles("ADMIN"); auth.inMemoryAuthentication() .withUser("wys") .password("123456") .roles("ADMIN"); auth.inMemoryAuthentication() .withUser("demo") .password("123456") .roles("USER"); // auth.userDetailsService(myUserService).passwordEncoder(new MyPasswordEncoder()); // 利用自定義的UserService進行管理 } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/").permitAll() // 主頁面請求攔截排除 .anyRequest().authenticated() // 除主頁面外的所有請求都會被攔截 .and() .logout().permitAll() // 註銷請求攔截排除 .and() .formLogin(); // 設置使用表單登錄的方式 http.csrf().disable(); // 關閉csrf驗證 } @Override public void configure(WebSecurity web) throws Exception { // 攔截排除設置 web.ignoring().antMatchers("/js/**", "/css/**", "/images/**"); } }
SpringSecurity配置類

3 編寫一些接口用於測試

技術分享圖片
package cn.xiangxu.spring_security_system;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
//@EnableGlobalMethodSecurity(prePostEnabled = true) // 開啟@PreAuthorize註解
public class SpringSecuritySystemApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringSecuritySystemApplication.class, args);
    }

    @GetMapping(value = "/")
    public String home() {
        return "Welcome to study springSecurity.";
    }

    @GetMapping(value = "/hello")
    public String hello() {
        return "hello boy";
    }

//    @PreAuthorize("hasRole(‘ROLE_ADMIN‘)") // 設定權限校驗:只用ADMIN角色才能調用該接口
    @GetMapping("/roleAuth")
    public String role() {
        return "admin role";
    }
}
View Code

4 請求測試接口

  利用硬編碼的用戶名和密碼進行登錄

  技術分享圖片

5 設置權限校驗

  5.1 在控制類上添加 @EnableGlobalMethodSecurity 註解

技術分享圖片
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.security.config.annotation.method.configuration;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({GlobalMethodSecuritySelector.class})
@EnableGlobalAuthentication
@Configuration
public @interface EnableGlobalMethodSecurity {
    boolean prePostEnabled() default false;

    boolean securedEnabled() default false;

    boolean jsr250Enabled() default false;

    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default 2147483647;
}
View Code

    @EnableGlobalMethodSecurity(prePostEnabled = true)

    代碼解釋:

      整個項目啟用方法角色驗證註解,prePostEnabled = true 表示啟用@PreAuthorize@PostAuthorize 兩個方法角色驗證註解(@PreFilter()@PostFilter() 也會被啟用)

  5.2 在需要進行角色驗證的接口上方添加 @PreAuthorize 註解

    @PreAuthorize("hasRole(‘ROLE_ADMIN‘)")

    代碼解釋:

      有該註解的方法只有角色是ADMIN的用戶才可以訪問

技術分享圖片
package cn.xiangxu.spring_security_system;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
@EnableGlobalMethodSecurity(prePostEnabled = true) // 開啟@PreAuthorize註解
public class SpringSecuritySystemApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringSecuritySystemApplication.class, args);
    }

    @GetMapping(value = "/")
    public String home() {
        return "Welcome to study springSecurity.";
    }

    @GetMapping(value = "/hello")
    public String hello() {
        return "hello boy";
    }

    @PreAuthorize("hasRole(‘ROLE_ADMIN‘)") // 設定權限校驗:只用ADMIN角色才能調用該接口
    @GetMapping("/roleAuth")
    public String role() {
        return "admin role";
    }
}
View Code

6 權限校驗註解

  6.1 @PreAuthorize

    在執行方法之前進行權限校驗

    6.1.1 角色驗證

      例如:@PreAuthorize("hasRole(‘ROLE_ADMIN‘) or hasRole(‘ROLE_USER‘)") // ADMIN USER 角色都有權限調用這個接口

技術分享圖片
package cn.xiangxu.spring_security_system;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
@EnableGlobalMethodSecurity(prePostEnabled = true) // 開啟@PreAuthorize註解
public class SpringSecuritySystemApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringSecuritySystemApplication.class, args);
    }

    @GetMapping(value = "/")
    public String home() {
        return "Welcome to study springSecurity.";
    }

    @GetMapping(value = "/hello")
    public String hello() {
        return "hello boy";
    }

    @PreAuthorize("hasRole(‘ROLE_ADMIN‘)") // 設定權限校驗:只用ADMIN角色才能調用該接口
    @GetMapping("/roleAuth")
    public String role() {
        return "admin role";
    }

    @PreAuthorize("hasRole(‘ROLE_ADMIN‘) or hasRole(‘ROLE_USER‘)") // ADMIN 和 USER 角色都有權限調用這個接口
    @GetMapping("/test01")
    public String rest01() {
        return "test01";
    }
}
View Code

    6.1.2 參數驗證01

      例如:@PreAuthorize("#id < 10")

        代碼解釋: 方法必須有id參數,而且參數的值必須小於10

        技術分享圖片

技術分享圖片
package cn.xiangxu.spring_security_system;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
@EnableGlobalMethodSecurity(prePostEnabled = true) // 開啟@PreAuthorize註解
public class SpringSecuritySystemApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringSecuritySystemApplication.class, args);
    }

    @GetMapping(value = "/")
    public String home() {
        return "Welcome to study springSecurity.";
    }

    @GetMapping(value = "/hello")
    public String hello() {
        return "hello boy";
    }

    @PreAuthorize("hasRole(‘ROLE_ADMIN‘)") // 設定權限校驗:只用ADMIN角色才能調用該接口
    @GetMapping("/roleAuth")
    public String role() {
        return "admin role";
    }

    @PreAuthorize("hasRole(‘ROLE_ADMIN‘) or hasRole(‘ROLE_USER‘)") // ADMIN 和 USER 角色都有權限調用這個接口
    @GetMapping("/test01")
    public String rest01() {
        return "test01";
    }

    @PreAuthorize("#id < 10")
    @GetMapping("/test02/{id}")
    public String test02(@PathVariable("id") Integer id) {
        return "test02 -> 獲取到的ID為:" + id;
    }
}
View Code

    6.1.3 參數驗證03

      例如:@PreAuthorize("principal.username.equals(#username)")

        代碼解釋:方法必須有username參數,而且參數的值必須是登錄用戶的用戶名

        技術分享圖片

技術分享圖片
package cn.xiangxu.spring_security_system;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
@EnableGlobalMethodSecurity(prePostEnabled = true) // 開啟@PreAuthorize註解
public class SpringSecuritySystemApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringSecuritySystemApplication.class, args);
    }

    @GetMapping(value = "/")
    public String home() {
        return "Welcome to study springSecurity.";
    }

    @GetMapping(value = "/hello")
    public String hello() {
        return "hello boy";
    }

    @PreAuthorize("hasRole(‘ROLE_ADMIN‘)") // 設定權限校驗:只用ADMIN角色才能調用該接口
    @GetMapping("/roleAuth")
    public String role() {
        return "admin role";
    }

    @PreAuthorize("hasRole(‘ROLE_ADMIN‘) or hasRole(‘ROLE_USER‘)") // ADMIN 和 USER 角色都有權限調用這個接口
    @GetMapping("/test01")
    public String rest01() {
        return "test01";
    }

    @PreAuthorize("#id < 10")
    @GetMapping("/test02/{id}")
    public String test02(@PathVariable("id") Integer id) {
        return "test02 -> 獲取到的ID為:" + id;
    }

    @PreAuthorize("principal.username.equals(#username)")
    @GetMapping("/test03")
    public String test03(@RequestParam("username") String username) {
        return "test03 -> 獲取到的username為:" + username;
    }
}
View Code

  6.2 @PostAuthorize

    在執行方法之後進行權限驗證

    例如:@PostAuthorize("returnObject.equals(‘test04‘)")

      代碼解釋:判斷方法的返回值是否等於 test04 , 如果是就通過驗證,如果不是就驗證失敗

      技巧:returnObject代表方法的返回對象

      技術分享圖片

技術分享圖片
package cn.xiangxu.spring_security_system;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
@EnableGlobalMethodSecurity(prePostEnabled = true) // 開啟@PreAuthorize註解
public class SpringSecuritySystemApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringSecuritySystemApplication.class, args);
    }

    @GetMapping(value = "/")
    public String home() {
        return "Welcome to study springSecurity.";
    }

    @GetMapping(value = "/hello")
    public String hello() {
        return "hello boy";
    }

    @PreAuthorize("hasRole(‘ROLE_ADMIN‘)") // 設定權限校驗:只用ADMIN角色才能調用該接口
    @GetMapping("/roleAuth")
    public String role() {
        return "admin role";
    }

    @PreAuthorize("hasRole(‘ROLE_ADMIN‘) or hasRole(‘ROLE_USER‘)") // ADMIN 和 USER 角色都有權限調用這個接口
    @GetMapping("/test01")
    public String rest01() {
        return "test01";
    }

    @PreAuthorize("#id < 10")
    @GetMapping("/test02/{id}")
    public String test02(@PathVariable("id") Integer id) {
        return "test02 -> 獲取到的ID為:" + id;
    }

    @PreAuthorize("principal.username.equals(#username)")
    @GetMapping("/test03")
    public String test03(@RequestParam("username") String username) {
        return "test03 -> 獲取到的username為:" + username;
    }

    @PostAuthorize("returnObject.equals(‘test04‘)")
    @GetMapping(value = "/test04")
    public String test04(@RequestParam("info") String info) {
        return info;
    }
}
View Code

  6.3 @PreFilter

    在方法執行前對列表型的參數進行一些驗證

    例如:@PreFilter("filterObject%2==0")

      ·代碼解釋:列表型的參數中的每個元素必須能被2整除

    技巧:filterObject 代表列表型的參數

  6.4 @PostFilter("filterObject%4 == 0")

    在方法執行後對返回的列表型對象進行一些驗證

     例如:@PostFilter("filterObject%4 == 0")

      代碼解釋:列表型的返回對象中的每個元素必須能被4整除

     技巧:filterObject 代表列表型的返回對象

SpringSecurity03 基於內存驗證