spring security +MySQL + BCryptPasswordEncoder 單向加密驗證 + 權限攔截 --- 心得


1.前言

前面學習了 security的登錄與登出 , 但是用戶信息 是 application 配置 或內存直接注入進去的 ,不具有實用性,實際上的使用還需要權限管理,有些 訪問接口需要某些權限才可以使用

於是多了個權限管理的問題

2.環境

spring boot 2.1.6.RELEASE

mysql 5.5.28*win64

jdk 1.8.0_221

3.操作

(1)准備一張MySQL表

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵,自遞增',
  `username` varchar(20) DEFAULT NULL COMMENT '用戶名',
  `psw` varchar(140) DEFAULT NULL COMMENT '密碼',
  `nickname` varchar(50) DEFAULT NULL COMMENT '別名',
  `role` varchar(100) DEFAULT NULL COMMENT '權限名',
  `setTime` datetime DEFAULT NULL COMMENT '注冊時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4;

 

 

 

 (2)目錄結構

(3)pom.xml

 

<?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.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>security-5500</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>security-5500</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <!-- 設置項目編碼格式-->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--spring security 依賴-->
        <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-thymeleaf</artifactId>
        </dependency>
        <!-- MySQL 依賴-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <!--            <scope>runtime</scope>-->
            <version>5.1.30</version>
        </dependency>
        <!--MySQL 數據源 依賴包-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

        <!--        mybatis依賴-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>
        <!-- mybatis的逆向工程依賴包-->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!-- SCryptPasswordEncoder 加密才需要使用-->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.64</version>
        </dependency>
        <!--java工具包-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </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>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-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>
View Code

 

(4)配置mybatis 與 dao層接口【具體操作這里不演示,可看我的其他隨筆有具體講解】

 

 

 (5)配置前端頁面

index.html

<!DOCTYPE html>
<html lang="zh" xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
你好 ,世界 ,2333
<p>點擊 <a th:href="@{/home}">我</a> 去home.html頁面</p>

</body>
</html>
View Code

 

home.html

<!DOCTYPE html>
<html lang="zh" xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <meta charset="UTF-8">
    <title>security首頁</title>
</head>
<body>
<h1>Welcome!你好,世界</h1>

<p>Click <a th:href="@{/hai}">here</a> to see a greeting.</p>
</body>
</html>
View Code

 

hai.html

<!DOCTYPE html>
<html lang="zh" xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <meta charset="UTF-8">
    <title>hai文件</title>
</head>
<body>
    你好呀世界,成功登錄進來了
<br>
<hr>
用戶名:<span th:text="${username}"></span>
<hr>
<!--  登出 路徑是在security 攔截規則 那 設置的   ,當然也可以使用自己寫的 ,必須post方式才可以訪問,因為默認開啟了CSRF -->
    <form th:action="@{/mylogout}" method="post">
        <button class="btn btn-danger" style="margin-top: 20px">退出登錄</button>
    </form>
</body>
</html>
View Code

 

kk.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>kk</title>
</head>
<body>
<img src="img/xx.png" alt="">
</body>
</html>
View Code

 

login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <title>Spring Security自定義</title>
</head>
<body>
<div th:if="${param.error}">
    Invalid username and password.
</div>
<div th:if="${param.logout}">
    You have been logged out.
</div>
<form th:action="@{/login}" method="post">
    <div><label> User Name : <input type="text" name="username"/> </label></div>
    <div><label> Password: <input type="password" name="password"/> </label></div>
    <div><input type="submit" value="Sign In"/></div>
</form>
<br>
lalallalalal啊是德國海
</body>
</html>
View Code

 

(6)配置controller 虛擬路徑 【訪問接口】

package com.example.security5500.controller;


import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import java.security.Principal;

@Controller
public class MVCController {

    @RequestMapping("/home")
    public String home() {
        return "home";
    }


    @RequestMapping("/login")
    public String login(){
        return "login";
    }


    @RequestMapping("/hai")
    public String hai(@AuthenticationPrincipal Principal principal, Model model) {
        //獲取登錄用戶名信息 ,如果沒有登錄  principal.getName() 會報異常,因此弄個異常拋出
        String  s= "r";
        try {
            if (principal.getName() !=null){
                s = principal.getName();
            }
        }catch (Exception e){
            System.out.println("principal.getName()出異常");
        }

        model.addAttribute("username", s);
        return "hai";
    }

    @RequestMapping({"/", "/index"})
    public String index() {
        return "index";
    }

    @RequestMapping("kk")
    public String kk() {
        return "kk";
    }


    //獲取用戶權限
    @RequestMapping({"/info"})
    @ResponseBody
    public Object info(@AuthenticationPrincipal Principal principal) {
        return principal;
    }
    /*
    {"authorities":[{"authority":"admin"},{"authority":"user"}],
    "details":{"remoteAddress":"0:0:0:0:0:0:0:1","sessionId":"1F57B8E39C5D1DB1F875D57D533DB982"},
    "authenticated":true,"principal":{"password":null,"username":"xi","authorities":[{"authority":"admin"},
    {"authority":"user"}],"accountNonExpired":true,"accountNonLocked":true,
    "credentialsNonExpired":true,"enabled":true},"credentials":null,"name":"xi"}

     */


}
View Code

 

package com.example.security5500.controller;


import com.example.security5500.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.Principal;
import java.util.Map;

@Controller
@RequestMapping("/admin")
public class UserController {

    @Autowired
    private UserService userService;

//    //登出操作
//    @RequestMapping({"/lo"})
//    public String logout(HttpServletRequest request, HttpServletResponse response) {
//        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
//        if (auth != null) {//清除認證
//            new SecurityContextLogoutHandler().logout(request, response, auth);
//        }
//        //重定向到指定頁面
//        return "redirect:/login";
//    }


    //添加用戶
    @RequestMapping({"/addUser"})
    @ResponseBody
    public Map<String,Object> addUser(String username , String psw ) {
        return userService.addUser(username,psw);
    }


}
View Code

 

 (7)service層實現類

package com.example.security5500.service.serviceImpl;

import com.example.security5500.dao.TUserMapper;
import com.example.security5500.entitis.tables.TUser;
import com.example.security5500.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


@Service
public class UserServiceImpl implements UserService {

    @Resource
    private TUserMapper tUserMapper;
    
    //根據用戶名獲取用戶信息
    @Override
    public TUser getByUsername(String useranme) {
        return tUserMapper.selectByUsername(useranme);
    }

    //添加新用戶
    @Override
    public Map<String,Object> addUser(String username, String psw) {
        Map<String,Object> map = new HashMap<>();
        if (StringUtils.isBlank(username) || StringUtils.isBlank(psw))
        {
            map.put("data","參數不可空");
            return map;
        }

        ////根據用戶名獲取用戶信息
        TUser u = tUserMapper.selectByUsername(username);
        if (u!= null){
            map.put("data","用戶名已經存在");
            return map;
        }
        //
        TUser tUser = new TUser();
        tUser.setUsername(username);
        //
        //BCryptPasswordEncoder 單向加密
        tUser.setPsw((new BCryptPasswordEncoder()).encode(psw));
        //
        tUser.setNickname("別名-昵稱");
        tUser.setRole("user");
        tUser.setSettime(new Date());
        int len = tUserMapper.insertSelective(tUser);
        if (len!=1){
            map.put("data","失敗");
        }else {
            map.put("data","成功");
        }
        return map;
    }
}
View Code

 

(8)啟動類

package com.example.security5500;

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;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@SpringBootApplication
//設置mapper接口包位置
@MapperScan(basePackages = "com.example.security5500.dao")
public class Security5500Application {

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


}
View Code

 

 

(9)security配置類 ,繼承了 WebSecurityConfigurerAdapter  ,重寫了父類方法 ,可對訪問路徑自定義設置攔截規則

 

package com.example.security5500.securityConfig;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

//這個加不加無所謂
//@Configuration
//開啟security自定義配置
@EnableWebSecurity
//開啟 Controller層的訪問方法權限,與注解@PreAuthorize("hasRole('admin')")配合,但是 經測試,無法使用,前端訪問指定接口報錯403 ,
//@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //實例自定義登錄校驗接口 【內部有 數據庫查詢】
    @Autowired
    private DbUserDetailsService dbUserDetailsService;

    //攔截規則設置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //允許基於使用HttpServletRequest限制訪問
                .authorizeRequests()
                //設置不攔截頁面,可直接通過,路徑訪問 "/", "/index", "/home" 則不攔截,
                
                .antMatchers("/", "/index", "/home", "/hhk/**")
                //是允許所有的意思
                .permitAll()
                //訪問 /hai 需要admin權限 ,無權限則提示 403
                .antMatchers("/hai").hasAuthority("admin")
                //訪問 /kk 需要admin或user權限 ,無權限則提示 403
                .antMatchers("/kk").hasAnyAuthority("admin","user")
                //路徑/admin/**所有的請求都需要admin權限 ,無權限則提示 403
                .antMatchers("/admin/**").hasAuthority("admin")
                //其他頁面都要攔截,【需要在最后設置這個】
                .anyRequest().authenticated()
                .and()
                //設置自定義登錄頁面
                .formLogin()
                //指定自定義登錄頁面的訪問虛擬路徑
                .loginPage("/login")
                .permitAll()
                .and()
//        添加退出登錄支持。當使用WebSecurityConfigurerAdapter時,這將自動應用。默認情況是,訪問URL”/ logout”,使HTTP Session無效
//        來清除用戶,清除已配置的任何#rememberMe()身份驗證,清除SecurityContextHolder,然后重定向到”/login?success”
                .logout()
//                //指定的登出操作的虛擬路徑,需要以post方式請求這個 http://localhost:5500/mylogout 才可以登出 ,也可以直接清除用戶認證信息達到登出目的
                .logoutUrl("/mylogout")
                //登出成功后訪問的地址
                .logoutSuccessUrl("/home");
    }


    /**
     * 添加 UserDetailsService, 實現自定義登錄校驗,數據庫查詢
     */
    @Override
    protected void configure(AuthenticationManagerBuilder builder) throws Exception {
        //注入用戶信息,每次登錄都會來這查詢一次信息,因此不建議每次都向mysql查詢,應該使用redis
        //密碼加密
        builder.userDetailsService(dbUserDetailsService).passwordEncoder(passwordEncoder());
    }

    /**
     * BCryptPasswordEncoder相關知識:
     * 用戶表的密碼通常使用MD5等不可逆算法加密后存儲,為防止彩虹表破解更會先使用一個特定的字符串(如域名)加密,然后再使用一個隨機的salt(鹽值)加密。
     * 特定字符串是程序代碼中固定的,salt是每個密碼單獨隨機,一般給用戶表加一個字段單獨存儲,比較麻煩。
     * BCrypt算法將salt隨機並混入最終加密后的密碼,驗證時也無需單獨提供之前的salt,從而無需單獨處理salt問題。
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


//    /**
//     * 選擇加密方式 ,密碼不加密的時候選擇 NoOpPasswordEncoder,不可缺少,否則報錯
//     * java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
//     */
//    @Bean
//    public static PasswordEncoder passwordEncoder() {
//        return NoOpPasswordEncoder.getInstance();
//    }


}
View Code

 

 

(10)實現自定義登錄校驗,實現了根據用戶名去數據庫查詢用戶信息,集齊參數用戶名、加密后的密碼、權限 , 

然后使用 new org.springframework.security.core.userdetails.User(tUser.getUsername(), tUser.getPsw(), simpleGrantedAuthorities); 注冊登錄用戶 ,

然后內部會自動對比密碼 進行校驗 【使用 BCryptPasswordEncoder 單項加密】

 

package com.example.security5500.securityConfig;


import com.example.security5500.entitis.tables.TUser;
import com.example.security5500.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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 java.util.ArrayList;
import java.util.List;

@Service
public class DbUserDetailsService implements UserDetailsService {

   @Autowired
   private UserService userService;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根據用戶名查詢用戶信息
        TUser tUser = userService.getByUsername(username);
        if (tUser == null){
            throw new UsernameNotFoundException("用戶不存在!");
        }
        //權限設置
//        List<GrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
        List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
        String role = tUser.getRole();
        //分割權限名稱,如 user,admin
        String[] roles = role.split(",");
        System.out.println("添加權限");
        for (String r :roles){
            System.out.println(r);
            //添加權限
            simpleGrantedAuthorities.add(new SimpleGrantedAuthority(r));
        }

//        simpleGrantedAuthorities.add(new SimpleGrantedAuthority("USER"));
        /**
         * 創建一個用於認證的用戶對象並返回,包括:用戶名,密碼,角色
         */
        //輸入參數
        return new org.springframework.security.core.userdetails.User(tUser.getUsername(), tUser.getPsw(), simpleGrantedAuthorities);
    }

}
View Code

 

 

(11)application.properties

spring.application.name=security-5500
# 應用服務web訪問端口
server.port=5500
#配置security登錄賬戶密和密碼  ,不配置則默認賬戶是user,密碼是隨機生成的字符串,打印在啟動欄中
#spring.security.user.name=11
#spring.security.user.password=22
#
##
##
##
## Enable template caching.
#spring.thymeleaf.cache=true
## Check that the templates location exists.
#spring.thymeleaf.check-template-location=true
## Content-Type value.
##spring.thymeleaf.content-type=text/html
## Enable MVC Thymeleaf view resolution.
#spring.thymeleaf.enabled=true
## Template encoding.
#spring.thymeleaf.encoding=utf-8
## Comma-separated list of view names that should be excluded from resolution.
#spring.thymeleaf.excluded-view-names=
## Template mode to be applied to templates. See also StandardTemplateModeHandlers.
#spring.thymeleaf.mode=HTML5
## Prefix that gets prepended to view names when building a URL.
##設置html文件位置
#spring.thymeleaf.prefix=classpath:/templates/
## Suffix that gets appended to view names when building a URL.
#spring.thymeleaf.suffix=.html  spring.thymeleaf.template-resolver-order=
# Order of the template resolver in the chain. spring.thymeleaf.view-names= # Comma-separated list of view names that can be resolved.
#
#
#設置mybatis
#mybatis設置
#mybatis配置文件所在路徑
mybatis.config-location=classpath:mybatis/config/mybatisConfig.xml
#所有Entity別名類所在包
mybatis.type-aliases-package=com.example.security5500.entitis.tables
#mapper映射xml文件[也可以放在 resources 里面]
#不論放在哪里,都必須使用classpath: 否則找不到 ,報錯 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
mybatis.mapper-locations= classpath:mybatis/mapper/**/*.xml


#mysql配置
# 當前數據源操作類型
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# mysql驅動包
spring.datasource.driver-class-name=org.gjt.mm.mysql.Driver
# 數據庫名稱
spring.datasource.url=jdbc:mysql://localhost:3306/security?characterEncoding=utf-8
# 數據庫賬戶名
spring.datasource.username=root
# 數據庫密碼
spring.datasource.password=mysql
#
#
# 數據庫連接池的最小維持連接數
spring.datasource.dbcp2.min-idle=5
# 初始化連接數
spring.datasource.dbcp2.initial-size=5
# 最大連接數
spring.datasource.dbcp2.max-total=5
# 等待連接獲取的最大超時時間
spring.datasource.dbcp2.max-wait-millis=200
#
# 指明是否在從池中取出連接前進行檢驗,如果檢驗失敗, 則從池中去除連接並嘗試取出另一個,
#注意: 設置為true后如果要生效,validationQuery參數必須設置為非空字符串
spring.datasource.druid.test-on-borrow=false
#
# 指明連接是否被空閑連接回收器(如果有)進行檢驗.如果檢測失敗,則連接將被從池中去除.
#注意: 設置為true后如果要生效,validationQuery參數必須設置為非空字符串
spring.datasource.druid.test-while-idle=true
#
# 指明是否在歸還到池中前進行檢驗,注意: 設置為true后如果要生效,
#validationQuery參數必須設置為非空字符串
spring.datasource.druid.test-on-return=false
#
# SQL查詢,用來驗證從連接池取出的連接,在將連接返回給調用者之前.
#如果指定,則查詢必須是一個SQL SELECT並且必須返回至少一行記錄
spring.datasource.druid.validation-query=select 1
View Code

 

 

 4.測試

 (1)啟動 默認進入 index.html

 

 

 點擊 “我” ,進入 home.html

 

 

點擊 “here”  ,進入 hai.html ,但是因為設置了攔截,需要登錄才可以訪問 ,因此進入了自定義的登錄頁面

 

 

用一個只有 user權限的賬戶  

username = cen 

password = 11

登錄后顯示 403

 

 因為我將訪問 hai.html的權限設為需要 admin 才可以訪問 ,因此拒絕操作

 

 

 換一個有admin權限的賬戶

 

username = xi

password = 11

訪問網址http://localhost:5500/login

再次登錄

 

 

 

 

 這是對一個終端訪問接口的權限攔截

 

那么,需要將某一路徑的請求都給攔截怎么辦?難道一個一個寫?

不,可以攔截上一層的虛擬路徑

 

 

 security的的配置寫法

 

 

(2)一個攔截路徑可以設置多個權限,只要有任意一個權限都可以訪問

 

 網址訪問 http://localhost:5500/kk  ,【無權限仍然提示403】

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM