shiro stateless

Demo of shiro session and stateless
安全框架shiro的一个同时支持无状态和session登录的添加部分自定义的demo

完整demo项目github源码

什么是shiro

官网地址

Shiro is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.

shiro是一个java服务端控制访问权限的安全框架

使用场景

由于公司手机端不能存cookie,所以传统的session存储登录信息的登录方式(后面简称session登录)不能用,所以需要一个既支持session登录后访问有访问权限控制的url又支持无状态化夹带加密token访问有访问权限控制的url的shiro配置。

这个demo适合以下几类情形人员服用:

  1. 面临上面我说的情况
  2. 接触过shiro,接触过spring boot。但不知道具体shiro拦截的是怎么起到作用的
  3. 接触过shiro,接触过spring boot。想把shiro 官方ini配置改写成java config配置的

这个demo不适合没有接触过shiro的人员,如果想要了解shiro基础的东西,推荐开涛的shiro的系列博客,地址
开涛博客 你们看完后会发现我的一些代码也是参考他的。我开始用shiro也是先看文档后看开涛的博客然后又参考了一些别的博客,再自己打断点看shiro源码来摸索的。

shiro默认访问步骤

shiro访问一个普通的url步骤大致是这样的

  1. 到 shiro 的 PathMatchingFilter preHandle 方法判断一个请求的访问权限是可以直接放行还是需要 shiro 自己实现的AccessControlFilter 来处理访问请求
  2. 假设到了 AccessControlFilter 实现类,首先在 isAccessAllowed 判断是否可以访问,如果可以则直接放行访问,如果不可以则到 onAccessDenied 方法处理,并继续调用 realm doGetAuthorizationInfo 授权判断是否有足够的权限来访问
  3. 假设有足够的权限的话就访问到自己定义的 controller了

如果这个url是登录请求的话,
那接下来:

  1. 在你自己的代码里会写到获取shiro的Subject,创建一个token,通常是UsernamePasswordToken,将请求参数的账户密码填充进去,然后调用subject.login(token)
  2. 接下来到支持处理这个token的realm中调用 realm doGetAuthenticationInfo 鉴权,鉴权后,session中就存有你的登录信息了

shiro开发步骤

原本shiro默认只支持session登录,不支持无状态形式的访问请求,只能做到阻止未登录用户访问需要访问权限的url,不符合我的需求。

要改的话就要看有没有一个东西来改变根据session控制访问逻辑。

可以实现 AccessControlFilter 来修改控制访问的逻辑

要做的有下面几方面

  • 自定义实现AccessControlFilter (StatelessAuthcFilter)
  • shiro的过滤链上添加自定义的filter
  • 自定义realm,不用账户密码登录鉴权(UsernamePasswordToken),而使用自定义的token传入加密字符串判断鉴权
  • 自定义一个token(TokenRealm),存储参数和加密参数等

自定义实现AccessControlFilter

自定义的filter继承AccessControlFilter类,主要改变了session登录判断是否登录的方式。AccessControlFilter有两个抽象接口,isAccessAllowed 和 onAccessDenied,如果isAccessAllowed返回true的话,就不会再判断用户是否有权限,所以isAccessAllowed直接返回false,在 onAccessDenied 方法里处理请求。

首先处理session登录方式的,onAccessDenied 方法有两个参数 ServletRequest request, ServletResponse response
用这两个参数可以获取subject,

Subject subject = getSubject(request, response);
if (subject.isAuthenticated()) return true;

如果已经登录,直接放行,就会继续授权,如果没有session信息,就继续向下判断是不是无状态方式的访问。

将请求参数填充自定义的 StatelessToken ,使用

subject.login(statelessToken);

让shiro调用自定义的 TokenRealm 来进行鉴权,鉴权通过的话,就和session登录的方式一样继续授权。

shiro的过滤链上添加自定义的filter

自定义实现的filter需要在自定义的shiro java config 类到ShiroFilterFactoryBean先注册一个名字,然后在用这个名字添加到filterChainDefinitionMap去(如果只想用session登录的方式的话,不用自定义的filter,只需在filterChainDefinitionMap添加"auth", 不需要控制权限的url添加"anon"就行)

    @Beanpublic ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setSecurityManager(securityManager);Map<String, Filter> filters = new HashMap();filters.put("statelessAuthc", statelessAuthcFilter());shiroFilterFactoryBean.setFilters(filters);// 拦截器Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了filterChainDefinitionMap.put("/login/logout", "logout");// 登录请求需要放行filterChainDefinitionMap.put("/login/sessionlogin", "anon");filterChainDefinitionMap.put("/login/statelesslogin", "anon");// 将想要纳入shiro statelessAuthc管理的放入mapfilterChainDefinitionMap.put("/user/*", "statelessAuthc");filterChainDefinitionMap.put("/**", "anon");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);return shiroFilterFactoryBean;}

statelessAuthcFilter 是我的AccessControlFilter实现类。
在访问时,所有访问的请求都会被拦截并进入PathMatchingFilter preHandle,将放入filterChainDefinitionMap的pattern字符串取出和请求地址匹配。

自定义realm

有多个realm的话,在config里配置ModularRealmAuthenticator,将自己的realm添加进去。
在用到realm的时候,进入 ModularRealmAuthenticator doMultiRealmAuthentication 判断使用哪个realm。
首先调用

public boolean supports(AuthenticationToken token)

判断这个realm是否支持,返回false的话shiro就不在这个realm上浪费时间了。调用完realm会根据配置时使用的调用策略来处理调用逻辑(是否继续调用,访问是否放行等)

有两个地方会调用到realm。一个是shiro 的 subject 调用login方法,根据token类型不同,会调用不同的realm的doGetAuthenticationInfo来鉴权;一个是调用AccessControlFilter实现类的onAccessDenied之后,如果判断用户可以继续访问就会继续调用realm的doGetAuthorizationInfo授权。

  • 授权 doGetAuthorizationInfo:

    从数据库或缓存读取用户身份信息,判断用户是否有访问这个资源的权限,这个所有realm处理逻辑都一样

  • 鉴权 doGetAuthenticationInfo

    session登录方式的鉴权只需要从数据库或缓存读取用户身份信息,判断密码是否正确,然后鉴权即可,无状态的登录方式需要使用加密token 鉴权。

自定义一个token

如果是账号密码登录的话,用shiro的UsernamePasswordToken就可以,但是因为需要在statelessAuthcFilter中调用login判断是否可以访问,所以需要增加一个支持自定义realm鉴权的token,这个token存储请求参数,用于tokenRealm鉴权对比前端加密token。

测试

接下来分别测试请求

  1. 不在config类filterChainDefinitionMap里的请求地址

  1. 在这个map里,过滤器anon(可以访问)的url

  1. 在这个map里,自定义shiro过滤器statelessAuthc的url

  1. session登录后访问不需要访问权限的请求

  1. session登录后访问需要user权限的请求

  1. 按自定义加密规则无状态化访问不需要user权限的请求

  1. 按自定义加密规则无状态化访问需要user权限的请求


使用加密token的原理

将前端的参数拼接成一条字符串,使用加密函数加密,将这个加密字符串作为请求签名和之前的参数一起发送到后端,后端收到参数后把请求签名剔除出来,剩下的参数采用和前端相同的加密函数加密,加密后的字符串和请求签名对比是否一样,如果一样服务端就认为这条请求是有效的,就继续放行判断对应的用户是否有权限访问

这样即使别人截获正常用户的请求想要做自己的不当用途,他的参数加密后和签名字符串不匹配的话访问就会失败,一定程度上的排除了恶意用户

为了增加安全性,可以选择加服务端提供的随机字符串和时间戳和其他参数同时加密,我只是在服务端加了随机字符串

shiro手机无状态登录访问和电脑端登录访问两种方式处理相关推荐

  1. 在program A里访问program B local class的两种方式

    Created by Jerry Wang on Jul 04, 2014 方式1 program A中定义并实现local class: class lcl_tool DEFINITION.PUBL ...

  2. java模拟网易邮箱登录_使用服务端和客户端两种方法 模拟网易邮箱实现全选,全不选的功能...

    服务端和客户端的差别是 服务端在每次全选或全不选是都要刷新界面 而客户端不会 服务端: 前台 DataKeyNames="id" DataSourceID="SqlDat ...

  3. SSH远程免密登录的两种方式

    SSH远程免密登录的两种方式 一.ssh远程登录操作 1.先ping测试下看看网络是否通畅 2.ssh 192.168.150.148 二.ssh免密登录方式一 1.生成公钥.私钥 2.拷贝公钥到目标 ...

  4. 同步手机QQ或微信消息到电脑端,需要时导入历史聊天记录

    一,同步消息 QQ电脑端: 1,电脑端设置,找到qq的设置. 2,点击下图,登录同步聊天记录. 手机QQ端: 只设置上面电脑端同步的话,在手机QQ上不会立刻显示在电脑端发送的信息.电脑端也不会立刻显示 ...

  5. 异域公主连接iOS怎么修改服务器,公主连结ios账号在电脑端登录方法 模拟器使用技巧分享...

    公主连结ReDive游戏中有着非常多的客户端,很多的ios玩家们想要在电脑上登录自己的账号,那么ios账号要怎么在电脑上登录呢?ios账号在电脑上登录的方法是什么样的呢?就和小编一起去了解一下在电脑上 ...

  6. Python itchat模块报错:为了你的帐号安全,此微信号不能登录网页微信。你可以使用Windows微信或Mac微信在电脑端登录。

    有谁知道Python itchat模块的问题? 我就写了两行代码: itchat.auto_login(True) friends = itchat.get_friends(update=True)[ ...

  7. windows远程连接Ubuntu16.04桌面版,有界面链接和无界面链接两种方式

    0.开放端口 Ubuntu自带一个ufw防火墙, 使用sudo ufw enable 启用防火墙, 然后开放5900和22端口 sudo ufw allow 22 sudo ufw allow 590 ...

  8. Spring Security 玩出花!两种方式 DIY 登录

    Spring Security 玩出花!两种方式 DIY 登录 一般情况下,我们在使用 Spring Security 的时候,用的是 Spring Security 自带的登录方案,配置一下登录接口 ...

  9. Spring Boot2 整合 Shiro ,两种方式全总结!

    前言:在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是,仅仅从技术角度来说,也可以使用 Shiro. 文章目录 一.Spring Securit ...

最新文章

  1. Java面试题汇总及答案2021最新(序列化含答案)
  2. 华人计算机视觉科学家黄煦涛逝世,众多AI大牛发文缅怀
  3. 深度学习核心技术精讲100篇(二十五)-58同城是如何构建智能化流量分发的?
  4. android6.0源码分析之AMS服务源码分析
  5. eclipse 如何忽略js文件报错
  6. 分组,命名分组,url的命名和反向解析
  7. 风靡全球的人工智能,如何赶上这班车?
  8. Java 8和Java 14之间的新功能
  9. jQuery实现radio第一次点击选中第二次点击取消功能(转)
  10. 性能计数器驱动_Vulkan 探密:AMD Vulkan 开源驱动源码解析-零
  11. mysql之join_mysql学习之join用法
  12. vue 引入json地图_vue中echarts引入中国地图
  13. Element属性:scrollHeight,clientHeight,offsetHeight区别
  14. vue安装(linux)
  15. 全国62个城市建筑轮廓矢量数据
  16. 手机android wifi的密码查看,手机怎么查看wif无线i密码?安卓手机忘记无线i密码查看方法...
  17. 分析亚马逊竞争对手Listing的技巧与操作步骤
  18. 为什么要引入齐次坐标,齐次坐标的意义(二)
  19. cs1.6 linux,在Ubuntu 8.04下玩CS1.6
  20. HashMap、Hashtable、HashSet和ConcurrentHashMap掐死版本

热门文章

  1. [转] 使用 DHTML 与 XML 制作 Ajax 幻灯片
  2. 小米手机 开发app python_python 全栈开发,Day59(小米商城)
  3. 前端入门学习笔记十九
  4. PCB布局布线中地的设计(地与地使用跨接)。
  5. ai怎么做波普风圆点_超实用AI描边小技巧:AI画一个圆点组成的圆
  6. 计算机怎么模拟对弈,剑网3指尖对弈怎么在电脑上玩 用模拟器玩剑网3指尖对弈电脑版...
  7. 刘盈盈计算机科学与技术,四川省2013年度中等职业学校省级优秀毕业生名单_29131...
  8. 韩国三星android多少钱,韩国首款安卓翻盖 三星GALAXY GOLDEN赏
  9. 【Vue3从零开始-实战】S14:详情页回退事件及路由参数的传递获取数据
  10. java第10章总结