Spring Security 基于URL的权限判断源码解析

目录
  • 1. FilterSecurityInterceptor 源码阅读
  • 2. 自定义基于url的授权

1. FilterSecurityInterceptor 源码阅读

org.springframework.security.web.access.intercept.FilterSecurityInterceptor

通过过滤器实现对HTTP资源进行安全处理。

该安全拦截器所需的 SecurityMetadataSource 类型为 FilterInvocationSecurityMetadataSource。

doFilter方法中直接调用invoke方法

基本都是调用父类的方法,那下面就重点看下父类 AbstractSecurityInterceptor中相关方法

为安全对象实现安全拦截的抽象类。

AbstractSecurityInterceptor 将确保安全拦截器的正确启动配置。 它还将实现对安全对象调用的正确处理,即:

1.从 SecurityContextHolder 获取 Authentication 对象。

2.通过在SecurityMetadataSource中查找安全对象请求,确定请求是与安全调用还是公共调用相关(PS:简单地来讲,就是看一下请求的资源是不是受保护的,受保护的就是安全调用,就要权限,不受保护的就不需要权限就可以访问)。

3.对于受保护的调用(有一个用于安全对象调用的 ConfigAttributes 列表):

  • 如果 Authentication.isAuthenticated() 返回 false,或者 alwaysReauthenticate 为 true,则根据配置的 AuthenticationManager 对请求进行身份验证。 通过身份验证后,将 SecurityContextHolder 上的 Authentication 对象替换为返回值。
  •  根据配置的AccessDecisionManager授权请求。
  • 通过配置的RunAsManager执行任何run-as替换。
  • 将控制权传递回具体的子类,它实际上将继续执行对象。返回一个 InterceptorStatusToken 以便在子类完成对象的执行后,其 finally 子句可以确保 AbstractSecurityInterceptor 被调用并使用 finallyInvocation(InterceptorStatusToken) 正确处理。
  • 具体的子类将通过 afterInvocation(InterceptorStatusToken, Object) 方法重新调用 AbstractSecurityInterceptor。
  • 如果 RunAsManager 替换了 Authentication 对象,则将 SecurityContextHolder 返回到调用 AuthenticationManager 后存在的对象。
  • 如果定义了AfterInvocationManager,则调用它并允许它替换将要返回给调用者的对象。

4.对于公开的调用(安全对象调用没有 ConfigAttributes):

如上所述,具体的子类将返回一个 InterceptorStatusToken,在执行完安全对象后,该 InterceptorStatusToken 随后被重新呈现给 AbstractSecurityInterceptor。 AbstractSecurityInterceptor 在它的 afterInvocation(InterceptorStatusToken, Object) 被调用时不会采取进一步的行动。

5.控制再次返回到具体的子类,以及应该返回给调用者的对象。然后子类会将该结果或异常返回给原始调用者。

下面具体来看

从这里我们可以知道返回null和空集合是一样的。

接下来看授权

这是我们要重点关注的,可以看到,授权靠的是accessDecisionManager.decide(authenticated, object, attributes)

因此,我们想要实现自己的基于请求Url的授权只需自定义一个 AccessDecisionManager即可

接下来,我们来具体实现一下

2. 自定义基于url的授权

先把Spring Security授权的大致流程流程摆在这儿:

自定义FilterInvocationSecurityMetadataSource

package com.example.security.core;

import com.example.security.service.SysPermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @Author ChengJianSheng
 * @Date 2021/12/2
 */
@Component
public class MyFilterSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    @Autowired
    private SysPermissionService sysPermissionService;

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        FilterInvocation fi = (FilterInvocation) object;
        String url = fi.getRequestUrl();
        String httpMethod = fi.getRequest().getMethod();

        List<ConfigAttribute> attributes = new ArrayList<>();

        Map<String, String> urlRoleMap = sysPermissionService.getAllUrlRole();

        for (Map.Entry<String, String> entry : urlRoleMap.entrySet()) {
            if (antPathMatcher.match(entry.getKey(), url)) {
                return SecurityConfig.createList(entry.getValue());
            }
        }

        // 返回null和空列表是一样的,都表示当前访问的资源不需要权限,所有人都可以访问
        return attributes;
//        return null;
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
}

这里需要说明一下,其实Spring Security里面说的role不一定表示的是我们自己建的那个角色表,我们可以这样理解,就是它这里的所谓role只是一个权限标识。我们在建表的时候,通常最基本的是5张表(用户表、角色表、权限表、用户角色关系表、角色权限关系表),我们可以把受保护的资源(通常是一个url)与角色关联起来,建立哪些角色可以访问哪些资源,也可以直接判断资源的权限(通常是权限编码/标识)。

只要有这个关系,剩下的就是写法不同而已。如果你把role理解成资源的权限标识的话,那么返回的Collection<ConfigAttribute>中就最多有一个元素,如果理解成角色的话,那么可能有多个元素。就这么点儿东西,写法不同而已,本质是一样的。

自定义AccessDecisionManager

package com.example.security.core;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;

import java.util.Collection;

/**
 * @Author ChengJianSheng
 * @Date 2021/12/2
 */
@Component
public class MyAccessDecisionManager implements AccessDecisionManager {
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        System.out.println(authorities);
        System.out.println(configAttributes);
        //  查看当前用户是否有对应的权限访问该保护资源
        for (ConfigAttribute attribute : configAttributes) {
            for (GrantedAuthority authority : authorities) {
                if (authority.getAuthority().equals(attribute.getAttribute())) {
                    return;
                }
            }
        }
        throw new AccessDeniedException("Access is denied");
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}

decide方法的三个参数,依次表示:

  • 调用者(非空)
  • 被调用的安全对象
  • 与被调用的安全对象关联的配置属性

配置WebSecurityConfig

package com.example.security.config;

import com.example.security.core.MyAccessDecisionManager;
import com.example.security.core.MyFilterSecurityMetadataSource;
import com.example.security.core.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;

/**
 * @Author ChengJianSheng
 * @Date 2021/12/6
 */
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailsService myUserDetailsService;
    @Autowired
    private MyAccessDecisionManager myAccessDecisionManager;
    @Autowired
    private MyFilterSecurityMetadataSource myFilterSecurityMetadataSource;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .and()
                .authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        object.setSecurityMetadataSource(myFilterSecurityMetadataSource);
                        object.setAccessDecisionManager(myAccessDecisionManager);
                        return object;
                    }
                })
                .anyRequest().authenticated();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

其它不重要的就直接贴出来了

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.6.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>security-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>security-demo</name>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </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>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </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>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/demo126?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
  jpa:
    database: mysql
    show-sql: true

SysPermissionEntity.java

package com.example.security.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.io.Serializable;

/**
 * @Author ChengJianSheng
 * @Date 2021/12/6
 */
@Getter
@Setter
@Entity
@Table(name = "sys_permission")
public class SysPermissionEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    /** 权限编码(标识) */
    private String code;

    /** 权限名称 */
    private String name;

    /** 权限URL */
    private String url;

}

SysRoleEntity.java

package com.example.security.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;

/**
 * @Author ChengJianSheng
 * @Date 2021/12/6
 */
@Getter
@Setter
@Entity
@Table(name = "sys_role")
public class SysRoleEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    /** 角色编码 */
    private String code;

    /** 角色名称 */
    private String name;

    @ManyToMany
    @JoinTable(name = "sys_role_permission", joinColumns = {@JoinColumn(name = "role_id")}, inverseJoinColumns = {@JoinColumn(name = "permission_id")})
    private Set<SysPermissionEntity> permissions;
}

SysUserEntity.java

package com.example.security.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;

/**
 * @Author ChengJianSheng
 * @Date 2021/12/6
 */
@Getter
@Setter
@Entity
@Table(name = "sys_user")
public class SysUserEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    /** 用户名 */
    private String username;

    /** 密码 */
    private String password;

    @ManyToMany
    @JoinTable(name = "sys_user_role",
            joinColumns = {@JoinColumn(name = "user_id")},
            inverseJoinColumns = {@JoinColumn(name = "role_id")})
    private Set<SysRoleEntity> roles;
}

SysUserRepository.java

package com.example.security.repository;

import com.example.security.entity.SysUserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

/**
 * @Author ChengJianSheng
 * @Date 2021/12/6
 */
public interface SysUserRepository extends JpaRepository<SysUserEntity, Integer>, JpaSpecificationExecutor<SysUserEntity> {

    SysUserEntity findByUsername(String username);
}

SysPermissionServiceImpl.java

package com.example.security.service.impl;

import com.example.security.entity.SysPermissionEntity;
import com.example.security.repository.SysPermissionRepository;
import com.example.security.service.SysPermissionService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author ChengJianSheng
 * @Date 2021/12/6
 */
@Service
public class SysPermissionServiceImpl implements SysPermissionService {

    @Resource
    private SysPermissionRepository sysPermissionRepository;

    @Override
    public Map<String, String> getAllUrlRole() {
        List<SysPermissionEntity> list = sysPermissionRepository.findAll();
        return list.stream().collect(Collectors.toMap(SysPermissionEntity::getUrl, SysPermissionEntity::getCode));
    }
}

MyUserDetails.java

package com.example.security.domain;

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.Set;

/**
 * @Author ChengJianSheng
 * @Date 2021/12/6
 */
@NoArgsConstructor
@AllArgsConstructor
public class MyUserDetails implements UserDetails {

    private String username;
    private String password;
    private boolean enabled;
    private Set<SimpleGrantedAuthority> authorities;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }
}

MyUserDetailsService.java

package com.example.security.core;

import com.example.security.domain.MyUserDetails;
import com.example.security.entity.SysPermissionEntity;
import com.example.security.entity.SysUserEntity;
import com.example.security.repository.SysUserRepository;
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 javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author ChengJianSheng
 * @Date 2021/12/6
 */
@Transactional
@Service
public class MyUserDetailsService implements UserDetailsService {

    @Resource
    private SysUserRepository sysUserRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUserEntity sysUserEntity = sysUserRepository.findByUsername(username);
        if (null == sysUserEntity) {
            throw new UsernameNotFoundException("用户不存在");
        }
        Set<SimpleGrantedAuthority> authorities = sysUserEntity.getRoles().stream()
                .flatMap(roleId->roleId.getPermissions().stream())
                .map(SysPermissionEntity::getCode)
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toSet());

        return new MyUserDetails(sysUserEntity.getUsername(), sysUserEntity.getPassword(), true, authorities);
    }
}

HelloController.java

package com.example.security.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author ChengJianSheng
 * @Date 2021/12/6
 */
@RestController
@RequestMapping("/hello")
public class HelloController {

    @GetMapping("/sayHello")
    public String sayHello() {
        return "Hello";
    }

    @GetMapping("/sayHi")
    public String sayHi() {
        return "Hi";
    }
}

数据库脚本如下

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for sys_permission
-- ----------------------------
DROP TABLE IF EXISTS `sys_permission`;
CREATE TABLE `sys_permission`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '权限编码(标识)',
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '权限名称',
  `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '权限URL',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_permission
-- ----------------------------
INSERT INTO `sys_permission` VALUES (1, 'home', '首页', '/home/**');
INSERT INTO `sys_permission` VALUES (2, 'user:add', '添加用户', '/user/add');
INSERT INTO `sys_permission` VALUES (3, 'user:delete', '删除用户', '/user/delete');
INSERT INTO `sys_permission` VALUES (4, 'hello:sayHello', '打招呼', '/hello/sayHello');

-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色编码',
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色名称',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES (1, 'employee', '员工');
INSERT INTO `sys_role` VALUES (2, 'engineer', '工程师');
INSERT INTO `sys_role` VALUES (3, 'leader', '组长');

-- ----------------------------
-- Table structure for sys_role_permission
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_permission`;
CREATE TABLE `sys_role_permission`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_id` int(11) NOT NULL COMMENT '角色ID',
  `permission_id` int(11) NOT NULL COMMENT '权限ID',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_role_permission
-- ----------------------------
INSERT INTO `sys_role_permission` VALUES (1, 1, 1);
INSERT INTO `sys_role_permission` VALUES (2, 2, 1);
INSERT INTO `sys_role_permission` VALUES (3, 2, 2);
INSERT INTO `sys_role_permission` VALUES (4, 3, 1);
INSERT INTO `sys_role_permission` VALUES (5, 3, 2);
INSERT INTO `sys_role_permission` VALUES (6, 3, 3);
INSERT INTO `sys_role_permission` VALUES (7, 3, 4);

-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES (1, 'zhangsan', '$2a$10$e4wFsFHQCNjPe5tTJMPkRuKGwmMGC45pfjMupY9nwbTuoKQ0bKc/u');

-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL COMMENT '用户ID',
  `role_id` int(11) NOT NULL COMMENT '角色ID',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES (1, 1, 1);
INSERT INTO `sys_user_role` VALUES (2, 1, 2);
INSERT INTO `sys_user_role` VALUES (3, 1, 3);

SET FOREIGN_KEY_CHECKS = 1;

浏览器访问http://localhost:8080/hello/sayHi 正常返回,不用登录,因为没有在sys_permission表中配置该资源,也就是说它不是一个受保护的资源(公开资源)

访问http://localhost:8080/hello/sayHello则需要先登录,用zhangsan登录成功以后正确返回

项目结构如下

到此这篇关于Spring Security 基于URL的权限判断的文章就介绍到这了,更多相关Spring Security权限判断内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring security用户URL权限FilterSecurityInterceptor使用解析

    这篇文章主要介绍了Spring security用户URL权限FilterSecurityInterceptor使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 用户通过浏览器发送URL地址,由FilterSecurityInterceptor判断是否具有相应的访问权限. 对于用户请求的方法权限,例如注解@PreAuthorize("hasRole('ADMIN')"),由MethodSecurityInterceptor判断

  • SpringSecurity实现动态url拦截(基于rbac模型)

    目录 1.了解主要的过滤器 1.SecurityMetadataSource 2.UserDetailsService 3.AccessDecisionManager 2.正式实战了 1 使用idea的Srping Initializr 创建一个项目 我的版本如下Pom.xml 2,创建一个springSecurity配置类,你也可以使用配置文件的方法.我这里使用了boot的配置类 3.自定义SecurityMetadataSource拦截器 后续会讲解如何实现方法拦截.其实与url拦截大同小异

  • springboot+springsecurity如何实现动态url细粒度权限认证

    谨记:Url表只储存受保护的资源,不在表里的资源说明不受保护,任何人都可以访问 1.MyFilterInvocationSecurityMetadataSource 类判断该访问路径是否被保护 @Component //用于设置受保护资源的权限信息的数据源 public class MyFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { @Bean public An

  • Spring Security 基于URL的权限判断源码解析

    目录 1. FilterSecurityInterceptor 源码阅读 2. 自定义基于url的授权 1. FilterSecurityInterceptor 源码阅读 org.springframework.security.web.access.intercept.FilterSecurityInterceptor 通过过滤器实现对HTTP资源进行安全处理. 该安全拦截器所需的 SecurityMetadataSource 类型为 FilterInvocationSecurityMetad

  • Spring AOP实现声明式事务机制源码解析

    目录 一.声明式全局事务 二.源码 三.小结: 一.声明式全局事务 在Seata示例工程中,能看到@GlobalTransactional,如下方法示例: @GlobalTransactional public boolean purchase(long accountId, long stockId, long quantity) { String xid = RootContext.getXID(); LOGGER.info("New Transaction Begins: " +

  • spring security中的默认登录页源码跟踪

    ​2021年的最后2个月,立个flag,要把Spring Security和Spring Security OAuth2的应用及主流程源码研究透彻! ​项目中使用过Spring Security的童鞋都知道,当我们没有单独自定义登录页时,Spring Security自己在初始化的时候会帮我们配置一个默认的登录页,之前一直疑问默认登录页是怎么配置的,今晚特地找了源码跟一下. springboot项目依赖 <dependency> <groupId>org.springframewo

  • Spring Security过滤器链加载执行流程源码解析

    目录 Spring Security实现原理 一.Spring Security过滤器链加载 1.注册名为 springSecurityFilterChain的过滤器 2.查看 DelegatingFilterProxy类 3.查看 FilterChainProxy类 3.1 查看 doFilterInternal方法. 3.2 查看 getFilters方法. 4 查看 SecurityFilterChain接口 5 查看 SpringBootWebSecurityConfiguration类

  • Spring源码解析容器初始化构造方法

    目录 前言 构造方法 前言 Spring框架被广泛应用于我们的日常工作中,但是很长时间以来我都是只会使用,不懂它的作用原理.通过最近一段时间的阅读源码,个人发现通过阅读源码,能够帮助我们了解Spring的设计理念,并且对Java编程中的一些设计模式更加熟悉,所以记录一下自己对Spring源码的理解. 在开始进行源码学习前,首先再回顾一下三种Spring编程风格: 基于Schema,即通过xml标签的配置方式 基于Annotation的注解技术,使用@Component等注解配置bean 基于Ja

  • Spring Security源码解析之权限访问控制是如何做到的

    〇.前文回顾 在实战篇<话说Spring Security权限管理(源码详解)>我们学习了Spring Security强大的访问控制能力,只需要进行寥寥几行的配置就能做到权限的控制,本篇来看看它到底是如何做到的. 一.再聊过滤器链 源码篇中反复提到,请求进来需要经过的是一堆过滤器形成的过滤器链,走完过滤器链未抛出异常则可以继续访问后台接口资源,而最后一个过滤器就是来判断请求是否有权限继续访问后台资源,如果没有则会将拒绝访问的异常往上向异常过滤器抛,异常过滤器会对异常进行翻译,然后响应给客户端

  • Spring Security基于散列加密方案实现自动登录功能

    目录 前言 一. 自动登录简介 1. 为什么要自动登录 2. 自动登录的实现方案 二. 基于散列加密方案实现自动登录 1. 配置加密令牌的key 2. 配置SecurityConfig类 3. 添加测试接口 4. 启动项目测试 三. 散列加密方案实现原理 1. cookie的加密原理分析 2. cookie的解码原理分析 3. 自动登录的源码分析 3.1 令牌生成的源码分析 3.2 令牌解析的源码分析 前言 在前面的2个章节中,一一哥 带大家实现了在Spring Security中添加图形验证码

  • Spring Security基于过滤器实现图形验证码功能

    目录 前言 一. 验证码简介 二. 基于过滤器实现图形验证码 1. 实现概述 2. 创建新模块 3. 添加依赖包 4. 创建Producer对象 5. 创建生成验证码的接口 6. 自定义异常 7. 创建拦截验证码的过滤器 8. 编写SecurityConfig 9. 编写测试页面 10. 代码结构 11. 启动项目测试 前言 在前两个章节中,一一哥 带大家学习了Spring Security内部关于认证授权的核心API,以及认证授权的执行流程和底层原理.掌握了这些之后,对于Spring Secu

  • SpringBoot集成Spring security JWT实现接口权限认证

    1.添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjw

随机推荐