Spring securty<九> 鉴权-自定义鉴权规则

Spring securty<九> 鉴权-自定义鉴权规则


本地项目的基础环境

环境版本
jdk1.8.0_201
maven3.6.0
Spring-boot2.3.3.RELEASE

1、简介

spring security是一个提供身份验证、授权和防止常见攻击的框架,它对命令式和反应式应用程序都有一流的支持,是保护基于Spring的应用程序的事实上的标准。详细可以参看《spring security官网》

《Spring securty<一> 简介入门案例》

《Spring securty<二> 配置项详解》

《Spring securty<三> 认证案例代码》

《Spring securty<四> 认证的源码解析》

《Spring securty<五> 认证–帐号/邮箱/手机号+密码》

《Spring securty<六> 认证–手机号+验证码》

《Spring securty<七> 认证–匿名用户拦截器源码分析》

《Spring securty<八> 鉴权–框架默认鉴权案例代码》

2、特性

2.1、身份验证

springsecurity作为身份验证,身份验证是验证试图访问特定资源的用户的身份的方法。对用户进行身份验证的常见方法是要求用户输入用户名和密码。一旦执行身份验证,我们就知道身份并可以执行授权。

2.2、资源保护,防止跨站点请求伪造(CSRF)

springsecurity提供了针对常见漏洞利用的保护。只要可能,默认情况下都会启用保护。

3、自定义鉴权规则

在上一篇的编码过程中,可以看到,每次权限的过程中,都需要去配置,或者项目启动的时候,去查询数据库,然后预定义进到代码里;

antMatchers("/test").hasRole("test").anyRequest().hasAuthority("admin");

或者通过注解的形式,编码到具体的请求上,这样,每次新增权限,或者修改权限的时候,就要修改代码,或者重启项目预定义会在项目启动的时候,加载到代码里);这样的缺点也是非常明显的;

并且每次异常的时候,都是返回的系统的英文异常,需要返回中文的指定异常;

有没有,通过权限的页面,对角色或者用户授权后,不需要重启项目或者修改的代码的方法?当然有,这个就需要自定义鉴权规则了;

下面就开始代码的编写了

3.1、复制项目代码

复制《Spring securty<八> 鉴权–框架默认鉴权案例代码》中的案例代码badger-spring-security-7

3.2、创建鉴权的接口

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.core.Authentication;

/**
 * 接口鉴权的方法
 * @author liqi
 */
public interface ResourcePermissionProcessor {

    boolean hasPermission(HttpServletRequest request, Authentication authentication);

}

3.3、鉴权接口的实现

package com.badger.spring.boot.security.config.access;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

/**
 * 接口鉴权的方法
 * @author liqi
 */
@Component("resourcePermissionService")
public class ResourcePermissionService implements ResourcePermissionProcessor {

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    public static final Map<String, List<String>> AUTH_MAP = new HashMap<>();

    static {
        AUTH_MAP.put("admin", Arrays.asList("/admin"));
        AUTH_MAP.put("ROLE_test", Arrays.asList("/test"));
    }

    @Override
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        // 当前用户所具有的权限
        final Set<String> authorityListToSet = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
        final String url = request.getRequestURI();// 当前请求的url
        for (String roleName : authorityListToSet) {
            List<String> list = AUTH_MAP.get(roleName);
            if (list != null) {
                final Optional<String> findAny = list.stream().filter(res -> {
                    // 通配符路径验证 eg: /sys/login/** --表示任意路径 "*"号
                    return antPathMatcher.match(res, url);
                }).findAny();
                if (findAny.isPresent()) {
                    return true;
                }
            }
        }
        // 异常不是鉴权异常的时候,异常无法向上抛出,异常处理的controller无法返回默认异常,需要把异常处理成鉴权异常
        throw new AuthenticationServiceException("没有访问url的权限:" + url);
    }
}

代码实现就比较简单了,从上下文中,拿到请求HttpServletRequest request以及,当前登录用户的会话信息Authentication authentication

然后拿到请求的url以及当前用户的角色信息,去跟数据库匹配就可以了,我这里,只是模拟了数据库的查询操作;

并且如果,鉴权失败了,还可以返回指定的中文异常;当然,你要是返回false,也是会返回系统的英文异常;

3.4、配置WebSecurityConfig类

之前的配置

	http.authorizeRequests().antMatchers(EXCLUDE_URLS).permitAll().antMatchers("/test").hasRole("test")
                .anyRequest().hasAuthority("admin");

替换的配置

   http.authorizeRequests().antMatchers(EXCLUDE_URLS).permitAll().anyRequest()
                .access("@resourcePermissionService.hasPermission(request,authentication)");

@:符号,固定写法

resourcePermissionService:为注入的实例的名称;

hasPermission:为方法名称

(request,authentication):从容器中,拿到的参数对象

4、测试演示

就不演示了,参考上一篇《Spring securty<八> 鉴权–框架默认鉴权案例代码》

详细的代码,可以查看《码云》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

葵花下的獾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值