SpringSecurity03 基於內存驗證

1 需求

  現有一個編寫好的系統,須要實現用戶登陸驗證便可,同時根據用戶的權限來限制用戶能夠訪問的接口css

 

2 編寫SpringSecurity配置類

  繼承 WebSecurityConfigurerAdapter 類並重寫configure 方法java

  

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配置類

   坑01:因爲從springboot2.0.3開始使用的springsecurity的版本是5.x,這個版本須要提供一個PasswordEncoder的實例,不然就會以下錯誤web

  解坑01之方法01:只須要建立一個PasswordEncoder的Bean並被spring容器所管理便可算法

    》建立一個實現了PasswordEncoder接口的實現類MyPasswordEncoder,在encode方法中編寫加密算法,在matches方法中編寫匹配算法spring

    》在配置文件中配置MyPasswordEncoder對應的Bean便可(在一個標註了@Configuration註解的類中添加下面的邏輯便可)springboot

  解坑01之方法02:在建立內存用戶的時候指定一個PasswordEncoder實例app

    》建立一個實現了PasswordEncoder接口的實現類MyPasswordEncoder,在encode方法中編寫加密算法,在matches方法中編寫匹配算法ide

    》建立內存用戶的時候直接指定PasswordEncoder便可post

 

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 表明列表型的返回對象

 

相關文章
相關標籤/搜索