怎么处理整合了shiro的应用的RPC接口鉴权问题

2024-06-22 07:28

本文主要是介绍怎么处理整合了shiro的应用的RPC接口鉴权问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这篇文章分享一下:当一个服务提供者整合了shiro安全框架来实现权限访问控制时,服务消费者通过feign请求服务提供者的接口时的鉴权不通过问题。

问题描述

博主有一个项目pms(权限管理系统),使用了shiro框架来实现鉴权功能,使用的是shiro内置的perms过滤器。

 而服务消费者端,通过feign访问RPC接口,很显然,由于是不同的项目,鉴权肯定是失败的。

package cn.edu.sgu.www.cms.feign.impl;import cn.edu.sgu.www.cms.dto.PermissionInitDTO;
import cn.edu.sgu.www.cms.entity.Permission;
import cn.edu.sgu.www.cms.entity.User;
import cn.edu.sgu.www.cms.feign.FeignService;
import cn.edu.sgu.www.cms.restful.JsonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;import java.util.List;
import java.util.Set;/*** 权限平台feign接口* @author heyunlin* @version 1.0*/
@FeignClient(name = "pms")
public interface PmsFeignService extends FeignService {/*** 根据用户名查询用户信息* @param username 用户名* @param service 应用名* @return JsonResult<User>*/@RequestMapping(value = "/user/selectByUsername", method = RequestMethod.GET)JsonResult<User> selectByUsername(@RequestParam("username") String username,@RequestParam("service") String service);/*** 权限数据初始化* @param permissionInitDTO 权限信息* @return JsonResult<Void>*/@RequestMapping(value = "/permission/resources", method = RequestMethod.POST)JsonResult<Void> resources(PermissionInitDTO permissionInitDTO);/*** 查询应用的非匿名子权限* @param service 应用名* @return JsonResult<List<Permission>>*/@RequestMapping(value = "/permission/selectPermissions", method = RequestMethod.GET)JsonResult<List<Permission>> selectPermissions(@RequestParam("service") String service);/*** 查询应用的匿名子权限* @param service 应用名* @return JsonResult<List<String>>*/@RequestMapping(value = "/permission/selectAnonymityPermissions", method = RequestMethod.GET)JsonResult<List<String>> selectAnonymityPermissions(@RequestParam("service") String service);/*** 通过用户名查询用户权限* @param username 用户名* @param service 应用名* @return JsonResult<Set<String>>*/@RequestMapping(value = "/permission/selectUserPermissions", method = RequestMethod.GET)JsonResult<Set<String>> selectUserPermissions(@RequestParam("username") String username,@RequestParam("service") String service);
}

而在服务消费者启动过程中,需要向pms查询当前应用的权限,所以导致feign请求报错,项目无法启动问题。

package cn.edu.sgu.www.cms.config;import cn.edu.sgu.www.cms.entity.Permission;
import cn.edu.sgu.www.cms.feign.impl.PmsFeignService;
import cn.edu.sgu.www.cms.restful.JsonResult;
import cn.edu.sgu.www.cms.shiro.UserRealm;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;/*** Shiro配置类* @author heyunlin* @version 1.0*/
@Configuration
public class ShiroConfig {@Value("${spring.application.name}")private String service;/*** 登录页面地址*/private String loginPage = "/login.html";/*** 未授权的URL*/private String unauthorizedUrl = "/user/unauthorized";private final PmsFeignService feignService;@Autowiredpublic ShiroConfig(PmsFeignService feignService) {this.feignService = feignService;}/*** 配置安全管理器* @param userRealm UserRealm* @return DefaultWebSecurityManager*/@Beanpublic DefaultWebSecurityManager securityManager(UserRealm userRealm, CacheManager cacheManager) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();// 设置缓存管理器securityManager.setCacheManager(cacheManager);// 把UserRealm注册到安全管理器securityManager.setRealm(userRealm);return securityManager;}/*** 配置Shiro过滤器工厂* @param securityManager 安全管理器* @return ShiroFilterFactoryBean*/@Beanpublic ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();// 注册安全管理器shiroFilterFactoryBean.setSecurityManager(securityManager);/** 设置登录页面的地址* 当用户访问认证资源的时候,如果用户没有登录,就会跳转到指定的页面*/shiroFilterFactoryBean.setLoginUrl(loginPage);/** 设置访问未授权资源时重定向的地址* 当用户访问需要授权才能访问资源的时候,如果用户没有该权限,就会跳转到指定的地址*/shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);// 定义资源访问规则Map<String, String> filterMap = new LinkedHashMap<>();/** 定义需要认证才能访问的资源*/filterMap.put("/", "authc");filterMap.put("/index.html", "authc");filterMap.put("/html/*.html", "authc");// knife4jfilterMap.put("/doc.html", "authc");filterMap.put("/v2/api-docs", "authc");filterMap.put("/swagger-resources", "authc");/** 定义不需要认证就能访问的资源*/filterMap.put(loginPage, "anon");filterMap.put("/user/login", "anon");filterMap.put(unauthorizedUrl, "anon");// 查询当前服务的所有匿名子权限JsonResult<List<String>> jsonResult = feignService.selectAnonymityPermissions(service);if (jsonResult.isSuccess()) {List<String> data = jsonResult.getData();for (String url : data) {filterMap.put(url, "anon");}}/** 定义需要指定权限才能访问的资源*/// 查询当前服务的所有非匿名子权限JsonResult<List<Permission>> result = feignService.selectPermissions(service);if (result.isSuccess()) {List<Permission> list = result.getData();for (Permission permission : list) {filterMap.put(permission.getUrl(), "perms[" + permission.getValue() + "]");}}shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);return shiroFilterFactoryBean;}}

之前就遇到了这个问题,但是一直没有管,因为当时还没有想到什么解决的办法。

今天写项目,又遇上了,真气人~

解决方案

博主想到的是通过设置一个请求头,通过过滤器鉴权时先判断请求头是否正确,正确的话直接返回true,不再进行后续的操作。

于是在feign的官网看一下有没有能设置请求头的方法,果然,找到一个请求拦截器可以达到这个效果~

添加请求头

定义一个RequestInterceptor,给请求设置一个请求头perms。

package cn.edu.sgu.www.cms.feign;import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;/*** @author heyunlin* @version 1.0*/
@Component
public class RequestHeaderInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {template.header("perms", "12345");}}

自定义过滤器

在服务生产者项目pms中定义一个过滤器PermsFilter,名字见名知义,就是shiro的perms过滤器。

重写shiro的perms过滤器(PermissionsAuthorizationFilter)的鉴权方法,先判断请求头是否为指定的值,如果是就跳过鉴权,直接返回true。

这样就避免了其他应用访问本应用的接口导致的鉴权失败问题了~

package cn.edu.sgu.www.pms.filter;import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;/*** 定义PermsFilter过滤器(覆盖shiro的perms过滤器)* @author heyunlin* @version 1.0*/
@Slf4j
public class PermsFilter extends PermissionsAuthorizationFilter {@Overridepublic boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {String perms = ((HttpServletRequest) request).getHeader("perms");if (perms != null && perms.equals("12345")) {log.debug("发现请求头perms,当前请求为搜权应用发起的请求,跳过鉴权~");return true;}return super.isAccessAllowed(request, response, mappedValue);}}

注册过滤器到shiro

将刚刚创建的过滤器注册到shiro,博主直接把原来的perms过滤器覆盖掉了。

// 自定义过滤器
Map<String, Filter> filterMap = new HashMap<>();filterMap.put("perms", new PermsFilter());shiroFilterFactoryBean.setFilters(filterMap);

好了,文章就分享到这里了,希望看完之后对你有所帮助~

这篇关于怎么处理整合了shiro的应用的RPC接口鉴权问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1083659

相关文章

AI绘图怎么变现?想做点副业的小白必看!

在科技飞速发展的今天,AI绘图作为一种新兴技术,不仅改变了艺术创作的方式,也为创作者提供了多种变现途径。本文将详细探讨几种常见的AI绘图变现方式,帮助创作者更好地利用这一技术实现经济收益。 更多实操教程和AI绘画工具,可以扫描下方,免费获取 定制服务:个性化的创意商机 个性化定制 AI绘图技术能够根据用户需求生成个性化的头像、壁纸、插画等作品。例如,姓氏头像在电商平台上非常受欢迎,

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in