SpringBoot整合Shiro流程

1.pom.xml导入shiro相关jar包

<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.0</version>
</dependency>
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>1.4.0</version>
</dependency>

2.封装Shiro配置类

在配置类中Realm,DefaultWebSecurityManager,ShiroFilterFactoryBean这三个Bean必须要配置的。

@Configuration
public class ShiroConfiguration {@Beanpublic ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setSecurityManager(securityManager);shiroFilterFactoryBean.setLoginUrl("/login");Map<String, Filter> filters = new LinkedHashMap<>();filters.put("authc", new JwtFilter());shiroFilterFactoryBean.setFilters(filters);Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();// 登录接口排除filterChainDefinitionMap.put("/login", "anon");// 退出登录接口排除filterChainDefinitionMap.put("/logout", "anon");// 图形验证码接口排除filterChainDefinitionMap.put("/captcha", "anon");anon(filterChainDefinitionMap);filterChainDefinitionMap.put("/**", "authc");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);return shiroFilterFactoryBean;}private void anon(Map<String, String> filterChainDefinitionMap) {filterChainDefinitionMap.put("/", "anon");filterChainDefinitionMap.put("/*.html", "anon");filterChainDefinitionMap.put("/favicon.ico", "anon");filterChainDefinitionMap.put("/css/**", "anon");filterChainDefinitionMap.put("/js/**", "anon");filterChainDefinitionMap.put("/beta/**", "anon");filterChainDefinitionMap.put("/fonts/**", "anon");filterChainDefinitionMap.put("/layui/**", "anon");filterChainDefinitionMap.put("/img/**", "anon");filterChainDefinitionMap.put("/v2/api-docs/**", "anon");filterChainDefinitionMap.put("/swagger-resources/**", "anon");filterChainDefinitionMap.put("/webjars/**", "anon");filterChainDefinitionMap.put("/pages/**", "anon");filterChainDefinitionMap.put("/druid/**", "anon");filterChainDefinitionMap.put("/statics/**", "anon");}@Beanpublic DefaultWebSecurityManager securityManager() {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();// 多realmSet<Realm> realms = new HashSet<>(MediaConstants.DEFAULT_COLLECTION_SIZE);realms.add(adminRealm());securityManager.setRealms(realms);// 关闭sessionDefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultSessionStorageEvaluator();sessionStorageEvaluator.setSessionStorageEnabled(false);subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator);securityManager.setSubjectDAO(subjectDAO);securityManager.setAuthenticator(authenticator());return securityManager;}@Beanpublic Authenticator authenticator() {ModularRealm modularRealm = new ModularRealm();modularRealm.setRealms(Arrays.asList(adminRealm()));modularRealm.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());return modularRealm;}@Beanpublic AdminShiroRealm adminRealm() {AdminShiroRealm mobileRealm = new AdminShiroRealm();mobileRealm.setName(LoginAdminTypeEnums.ADMIN_USER.value);return mobileRealm;}@Bean@DependsOn("lifecycleBeanPostProcessor")public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);return defaultAdvisorAutoProxyCreator;}@Beanpublic LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}@Beanpublic AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();advisor.setSecurityManager(securityManager);return advisor;}}

3.配置Realm

Realm中主要涉及用户身份验证和授权策略信息的设置

@Data
public class AdminShiroRealm extends AuthorizingRealm {@Autowiredprivate UserAuthService userAuthMgr;/*** 使用JWT替代原生Token** @param token* @return*/@Overridepublic boolean supports(AuthenticationToken token) {return token instanceof JwtToken;}private static final String ADMIN_USER_LOGIN_TYPE = LoginAdminTypeEnums.ADMIN_USER.value;{// 设置realm的名字,非常重要super.setName(ADMIN_USER_LOGIN_TYPE);}/*** 功能: 获取用户权限信息,包括角色以及权限。只有当触发检测用户权限时才会调用此方法,例如checkRole,checkPermission** @return AuthorizationInfo 权限信息*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {String sid = JwtUtil.getSid(principals.toString());SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();// 查询用户权限List<String> userAuthList = userAuthMgr.getAuthority(sid);if (!CollectionUtils.isEmpty(userAuthList)) {Set<String> userAuthorities = new HashSet<>(userAuthList);authorizationInfo.setStringPermissions(userAuthorities);}return authorizationInfo;}/*** 功能: 用来进行身份认证,也就是说验证用户输入的账号和密码是否正确,获取身份验证信息,错误抛出异常** @return 返回封装了用户信息的 AuthenticationInfo 实例*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {String token = (String) auth.getCredentials();if (StringUtils.isEmpty(token)) {throw new AuthenticationException("token非法无效!");}String loginAccount = JwtUtil.getLoginAccount(token);String loginType = JwtUtil.getLoginType(token);if (loginAccount == null || loginType == null) {throw new AuthenticationException("token非法无效!");}if (!JwtUtil.verify(token, loginAccount)) {throw new AuthenticationException("token失效,请重新登录!");}return new SimpleAuthenticationInfo(token, token, getName());}
}

4.涉及到的工具类

/*** 鉴权登录拦截器***/
public class JwtFilter extends BasicHttpAuthenticationFilter {private static final Logger logger = LoggerFactory.getLogger(JwtFilter.class);private static String AUTHORIZATION = "Authorization";@Overrideprotected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {HttpServletRequest httpServletRequest = (HttpServletRequest) request;String token = httpServletRequest.getHeader(AUTHORIZATION);String loginType = JwtUtil.getLoginType(token);JwtToken jwtToken = new JwtToken(token,loginType);// 提交给realm进行登入,如果错误他会抛出异常并被捕获getSubject(request, response).login(jwtToken);// 如果没有抛出异常则代表登入成功,返回truereturn true;}@Overrideprotected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {if (isLoginRequest(request, response)) {try {return super.onAccessDenied(request, response);} catch (Exception e) {logger.error("onAccessDenied Exception", e);return false;}}try {// 接口需要登录return executeLogin(request, response);} catch (Exception e) {return false;}}@Overrideprotected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {//访问拒绝的逻辑if (isLoginRequest(request, response)) {return false;} // 未登录Subject subject = getSubject(request, response);if (subject == null || subject.getPrincipal() == null) {WebUtils.responseJsonText(response, ApiResponse.of("401", "un login"));return false;}return super.onAccessDenied(request, response);}@Overrideprotected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request,ServletResponse response) {logger.warn("onLoginFailure AuthenticationToken={},AuthenticationException={}", token);try {WebUtils.responseJsonText(response, ApiResponse.of("500", e.getMessage()));} catch (IOException e1) {logger.error("response error", e);return false;}return false;}@Overrideprotected String getHost(ServletRequest request) {return WebUtils.getHost(request);}}
public class JwtUtil {public static final String SID = "sid"; public static final String LOGIN_ACCOUNT = "loginAccount";/*** 机构id*/public static final String ORGANIZATION_ID = "organizationId"; /*** 登录类型*/public static final String LOGIN_TYPE = "loginType";/*** 登录昵称*/public static final String LOGIN_NICKNAME = "loginNickname";/*** 校验token是否正确* * @param token  密钥* @param loginAccount 登录账号* @return 是否正确*/public static boolean verify(String token, String loginAccount) {try {Long userId = getUserId(token);Algorithm algorithm = Algorithm.HMAC256(Md5Utils.md5Hex(userId.toString()));JWTVerifier verifier = JWT.require(algorithm).withClaim(LOGIN_ACCOUNT, loginAccount).build();verifier.verify(token);return true;} catch (Exception exception) {return false;}}/*** 获得token中的信息无需secret解密也能获得* * @return token中包含的用户名*/public static String getLoginAccount(String token) {try {DecodedJWT jwt = JWT.decode(token);return jwt.getClaim(LOGIN_ACCOUNT).asString();} catch (JWTDecodeException e) {return null;}}/*** 获得token中的信息无需secret解密也能获得** @return token中包含的用户名*/public static String getLoginNickname(String token) {try {DecodedJWT jwt = JWT.decode(token);return jwt.getClaim(LOGIN_NICKNAME).asString();} catch (JWTDecodeException e) {return null;}}public static Long getUserId(String token) {if(StringUtils.isEmpty(token)) {return null;}try {DecodedJWT jwt = JWT.decode(token);return Long.parseLong(jwt.getSubject());} catch (JWTDecodeException e) {return null;}}public static String getSid(String token) {if(StringUtils.isEmpty(token)) {return null;}try {DecodedJWT jwt = JWT.decode(token);return jwt.getClaim(SID).asString();} catch (JWTDecodeException e) {return null;}}/*** 后台管理员生成签名* @param loginAccount 用户名* @return 加密的token*/public static String signAdmin(String loginAccount,Long userId,String sid,String loginType,String nickName) {try {loginAccount = StringUtils.lowerCase(loginAccount);Algorithm algorithm = Algorithm.HMAC256(Md5Utils.md5Hex(userId.toString()));return JWT.create().withClaim(LOGIN_ACCOUNT, loginAccount).withClaim(SID, sid).withClaim(LOGIN_TYPE, loginType).withClaim(LOGIN_NICKNAME,nickName).withSubject(String.valueOf(userId)).withExpiresAt(new Date(System.currentTimeMillis() + CacheExpiresTime.ADMIN_EXPIRE_TIME_MILLISECOND)).sign(algorithm);} catch (Exception e) {return null;}}public static String getLoginType(String token) {try {DecodedJWT jwt = JWT.decode(token);return jwt.getClaim(LOGIN_TYPE).asString();} catch (JWTDecodeException e) {return null;}}/*** * title: 获取当前登录用户的机构id* @param token* @return*/public static Long getOrganizationId(String token) {if(StringUtils.isEmpty(token)) {return null;}try {DecodedJWT jwt = JWT.decode(token);return jwt.getClaim(ORGANIZATION_ID).asLong();} catch (JWTDecodeException e) {return null;}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/845578.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

注意力可视化代码

读取网络层输出的特征到txt文件&#xff0c;arr为文件名 def hot(self, feature, arr):# 在第二维&#xff08;通道维&#xff09;上相加summed_tensor torch.sum(feature, dim1, keepdimTrue) # 结果形状为 [1, 1, 64, 64]selected_matrix summed_tensor.squeeze(1) # 移除…

牛客小白月赛95

c相助 题目描述 此题为E题的easy版&#xff0c;只有aia_iai​的数据范围不同。 给你一个 nnn 个正整数组成的数组 a &#xff0c;你每次操作可以选择一对 (i,j)( i, j )(i,j)&#xff0c;满足 1≤i<j≤n1 \leq i < j \leq n1≤i<j≤n&#xff0c;且 aiaja_{i} a_{…

三丰云免费服务器

三丰云网址&#xff1a; https://www.sanfengyun.com 可申请免费云服务器&#xff0c;1核/1G内存/5M宽带/有公网IP/10G SSD硬盘/免备案。 收费云服务器&#xff0c;买2年送1年&#xff0c;有很多优惠

Lombok一文通

1、Lombok简介 作为java的忠实粉丝&#xff0c;但也不得不承认&#xff0c;java是一门比较啰嗦的语言&#xff0c;很多代码的编写远不如其他静态语言方便&#xff0c;更别说跟脚本语言比较了。 因此&#xff0c;lombok应运而生。 Lombok是一种工具库&#xff0c;它提供了一组…

msf攻击windows实例

环境&#xff1a;攻击机kali&#xff08;192.168.129.139&#xff09;&#xff0c;目标机windows10&#xff08;192.168.129.132&#xff09; 方法一&#xff1a;通过web站点&#xff0c;使用无文件的方式攻击利用执行&#xff08;命令执行漏洞&#xff09; 方法二&#xff1…

迪文 51单片机,全局变量、静态变量初始化失败,修正

1. 问题 51单片机全局变量常量的初始化&#xff0c;static code const函数内部静态变量初始化也失败&#xff0c;例如 void fun() {static int a 5;printf("a %d\n", a); //输入的不一定是5&#xff0c;是之前这个地址的值&#xff08;随机值&#xff09; }2. 解决…

Lua两个点号连接字符串

在Lua中&#xff0c;两个点号 .. 代表字符串连接操作符。当你想要将两个或多个字符串拼接在一起时&#xff0c;可以使用这个操作符。 以下是使用 .. 操作符的一些示例&#xff1a; local str1 "Hello, " local str2 "World!" local result str1 .. str2…

提示工程(Prompt Engineering)和代码生成

文心一言 提示工程&#xff08;Prompt Engineering&#xff09;和代码生成之间的关系主要体现在如何通过精心设计的提示来指导或优化代码生成的过程。以下是关于提示工程和代码生成的详细解释&#xff1a; 一、提示工程&#xff08;Prompt Engineering&#xff09; 提示工程…

路径操作函数

System.SysUtils.AnsiCompareFileName 根据当前语言环境比较文件名。 在 Windows 下不区分大小写&#xff0c;在 MAC OS 下区分大小写。 在不使用多字节字符集 (MBCS) 的 Windows 区域设置下&#xff0c;AnsiCompareFileName 与 AnsiCompareText 相同。在 MAC OS 和 Linux 下&…

KotlinConf 2024:深入了解Kotlin Multiplatform (KMP)

KotlinConf 2024&#xff1a;深入了解Kotlin Multiplatform (KMP) 在近期的Google I/O大会上&#xff0c;我们推荐了Kotlin Multiplatform (KMP)用于跨移动、网页、服务器和桌面平台共享业务逻辑&#xff0c;并在Google Workspace中采用了KMP。紧接着&#xff0c;KotlinConf 2…

【设计模式深度剖析】【7】【结构型】【享元模式】| 以高脚杯重复使用、GUI中的按钮为例说明,并对比Java类库设计加深理解

&#x1f448;️上一篇:外观模式 | 下一篇:结构型设计模式对比&#x1f449;️ 设计模式-专栏&#x1f448;️ 目录 享元模式定义英文原话直译如何理解&#xff1f;字面理解例子&#xff1a;高脚杯的重复使用例子&#xff1a;GUI中的按钮传统方式使用享元模式 4个角色1. …

锻压设备智能制造工厂物联数字孪生平台,推进制造业数字化转型

锻压设备智能制造工厂物联数字孪生平台&#xff0c;推进制造业数字化转型。随着全球制造业的飞速发展&#xff0c;数字化转型已经成为企业提升竞争力、实现可持续发展的关键。在锻压设备智能制造领域&#xff0c;工业物联数字孪生平台以其强大的数据集成、分析和管理能力&#…

国际物流管理系统的选择:花钱不怕,就怕花冤枉钱

现在市场上的国际物流管理系统还是非常多的&#xff0c;想在这么多类型的系统中选择一套适合自己的系统确实不是个简单的事情。 尤其是现在很多物流商其实都是比较小的国际物流商&#xff0c;很多大型的&#xff0c;过于复杂的系统并不适合这个群体。那这个群体应该怎么选择国…

什么是Java序列化?它有什么用途?

Java序列化&#xff08;Serialization&#xff09;是将Java对象转换为字节流的过程&#xff0c;反序列化&#xff08;Deserialization&#xff09;则是将字节流恢复为Java对象的过程。Java的序列化机制使得对象的持久化和跨网络传输成为可能。 Java序列化的用途 持久化存储&am…

mfc140u.dll丢失的解决方法有哪些?怎么全面修复mfc140u.dll文件

mfc140u.dll丢失其实相对来说不太常见到&#xff0c;因为这个文件一般是不丢失的&#xff0c;不过既然有人遇到这种问题&#xff0c;那么小编一定满足各位&#xff0c;给大家详细的唠叨一下mfc140u.dll丢失的各种解决方法&#xff0c;教大家以最快最有效率的方法去解决mfc140u.…

【Redis】Redis分片集群中数据的存储和读取

Redis 分片集群&#xff08;Sharded Cluster&#xff09;通过将数据分散到多个节点上来实现高可用性和可扩展性。它采用一致性哈希&#xff08;Consistent Hashing&#xff09;或其他哈希算法来将键分配到不同的分片中。每个分片由一个或多个 Redis 实例组成&#xff0c;这些实…

Spring MVC 源码分析之 DispatcherServlet#getHandlerAdapter 方法

前言&#xff1a; 前面我们分析了 Spring MVC 的工作流程源码&#xff0c;其核心是 DispatcherServlet#doDispatch 方法&#xff0c;我们前面分析了获取 Handler 的方法 DispatcherServlet#getHandler 方法&#xff0c;本篇我们重点分析一下获取当前请求的适配器 HandlerAdapt…

C语言练习题之——从简单到烧脑(13)(每日两道)

打印爱心 1.1:普通输出爱心 #include<stdio.h> int main() {printf(" ********* *********\n"); //7&#xff08;代表边上的空格&#xff09;printf(" *************** ***************\n"); //4printf(" ************…

AI播客下载:a16z (主题为AI、web3、生物技术等风险投资)

a16z播客是一个综合性的科技和创新领域的媒体平台&#xff0c;通过多种节目形式和丰富的内容&#xff0c;为广大听众提供了一个了解最新科技趋势和创新思维的窗口。a16z播客是由安德里森霍罗威茨&#xff08;Andreessen Horowitz&#xff0c;简称a16z&#xff09;推出的一个科技…

汽车MCU虚拟化--对中断虚拟化的思考(1)

目录 1.中断虚拟化的困惑 2.从R52入手 3.小结 1.中断虚拟化的困惑 在车控类控制器里&#xff0c;中断对于我们来说是非常宝贵的资源&#xff0c;可大幅提高系统实时性。 这些中断基本都属于实际物理硬中断(软中断另说)&#xff0c;例如对一个按键按下的中断响应&#xff0…