websecurity连接mysql_Spring Security 动态url权限控制(三)

一、前言

本篇文章将讲述Spring Security 动态分配url权限,未登录权限控制,登录过后根据登录用户角色授予访问url权限

基本环境

spring-boot 2.1.8

mybatis-plus 2.2.0

mysql 数据库

maven项目

Spring Security入门学习可参考之前文章:

二、数据库建表

8f612224ced769034e9ba284c28a6e02.png

表关系简介:

用户表t_sys_user 关联 角色表t_sys_role 两者建立中间关系表t_sys_user_role

角色表t_sys_role 关联 权限表t_sys_permission 两者建立中间关系表t_sys_role_permission

最终体现效果为当前登录用户所具备的角色关联能访问的所有url,只要给角色分配相应的url权限即可

温馨小提示:这里逻辑根据个人业务来定义,小编这里讲解案例只给用户对应的角色分配访问权限,像其它的 直接给用户分配权限等等可以自己实现

表模拟数据如下:

498181bcf71869bf23660a43800bb01c.png

三、Spring Security 动态权限控制

1、未登录访问权限控制

自定义AdminAuthenticationEntryPoint类实现AuthenticationEntryPoint类

这里是认证权限入口 -> 即在未登录的情况下访问所有接口都会拦截到此(除了放行忽略接口)

温馨小提示:ResponseUtils和ApiResult是小编这里模拟前后端分离情况下返回json格式数据所使用工具类,具体实现可参考文末给出的demo源码

@Component

public class AdminAuthenticationEntryPoint implements AuthenticationEntryPoint {

@Override

public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) {

ResponseUtils.out(response, ApiResult.fail("未登录!!!"));

}

}

2、自定义过滤器MyAuthenticationFilter继承OncePerRequestFilter实现访问鉴权

每次访问接口都会经过此,我们可以在这里记录请求参数、响应内容,或者处理前后端分离情况下,以token换用户权限信息,token是否过期,请求头类型是否正确,防止非法请求等等

logRequestBody()方法:记录请求消息体

logResponseBody()方法:记录响应消息体

【注:请求的HttpServletRequest流只能读一次,下一次就不能读取了,因此这里要使用自定义的MultiReadHttpServletRequest工具解决流只能读一次的问题,响应同理,具体可参考文末demo源码实现】

@Slf4j

@Component

public class MyAuthenticationFilter extends OncePerRequestFilter {

private final UserDetailsServiceImpl userDetailsService;

protected MyAuthenticationFilter(UserDetailsServiceImpl userDetailsService) {

this.userDetailsService = userDetailsService;

}

@Override

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

System.out.println("请求头类型: " + request.getContentType());

if ((request.getContentType() == null && request.getContentLength() > 0) || (request.getContentType() != null && !request.getContentType().contains(Constants.REQUEST_HEADERS_CONTENT_TYPE))) {

filterChain.doFilter(request, response);

return;

}

MultiReadHttpServletRequest wrappedRequest = new MultiReadHttpServletRequest(request);

MultiReadHttpServletResponse wrappedResponse = new MultiReadHttpServletResponse(response);

StopWatch stopWatch = new StopWatch();

try {

stopWatch.start();

// 记录请求的消息体

logRequestBody(wrappedRequest);

// String token = "123";

// 前后端分离情况下,前端登录后将token储存在cookie中,每次访问接口时通过token去拿用户权限

String token = wrappedRequest.getHeader(Constants.REQUEST_HEADER);

log.debug("后台检查令牌:{}", token);

if (StringUtils.isNotBlank(token)) {

// 检查token

SecurityUser securityUser = userDetailsService.getUserByToken(token);

if (securityUser == null || securityUser.getCurrentUserInfo() == null) {

throw new AccessDeniedException("TOKEN已过期,请重新登录!");

}

UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(securityUser, null, securityUser.getAuthorities());

// 全局注入角色权限信息和登录用户基本信息

SecurityContextHolder.getContext().setAuthentication(authentication);

}

filterChain.doFilter(wrappedRequest, wrappedResponse);

} finally {

stopWatch.stop();

long usedTimes = stopWatch.getTotalTimeMillis();

// 记录响应的消息体

logResponseBody(wrappedRequest, wrappedResponse, usedTimes);

}

}

private String logRequestBody(MultiReadHttpServletRequest request) {

MultiReadHttpServletRequest wrapper = request;

if (wrapper != null) {

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值