将 Apache Shiro 改造成 JWT 认证方式
来源:互联网 发布:知乎俄罗斯航空发动机 编辑:程序博客网 时间:2024/05/29 01:55
要想成功改造,只需做到三点
- 用 Shiro 提供的 DefaultWebSessionManager 替代默认的 ServletContainerSessionManager
- ServletContainerSessionManager 是 DefaultWebSecurityManager 使用的默认实现,用于 Web 环境,其直接使用 Servlet 容器的会话
- 因为我们无法控制服务器(例如 Tomcat)的会话管理,所以要自己维护会话池,即使用 DefaultWebSessionManager
- 自定义 SessionIdCookie 模板,其默认从 Cookie 读取 SessionId,但我们需要从请求头部读取 Token 字段
- 自定义 SessionIdGenerator,默认的 JavaUuidSessionIdGenerator 产生一个随机的 UUID 值来做 SessionId,但我们需要用 jwt 串作 SessionId
shiro.ini
[main]#自定义会话 Cookie 模板,重写方法,使得从请求头部或参数读取 SessionId,而非 CookiesessionIdCookie=com.pomer.test.servlet.MySimpleCookie#使用 Shiro 提供的 DefaultWebSessionManager,其维护自己的会话池,从而废弃服务器的会话池sessionManager=org.apache.shiro.web.session.mgt.DefaultWebSessionManagersessionIdCookie.name=Token#sessionIdCookie.domain=sishuok.com#sessionIdCookie.path=#sessionIdCookie.maxAge=1800sessionIdCookie.httpOnly=truesessionManager.sessionIdCookie=$sessionIdCookiesessionManager.sessionIdCookieEnabled=true#自定义会话 ID 生成器(SessionId 返回 JWT 串,而非随机 UUID)sessionIdGenerator=com.pomer.test.servlet.MySessionIdGenerator#如果考虑分布式服务器,可以自定义数据库存储会话 Dao,这里使用了内存存取会话sessionDAO=org.apache.shiro.session.mgt.eis.MemorySessionDAOsessionDAO.sessionIdGenerator=$sessionIdGeneratorsessionManager.sessionDAO=$sessionDAOsecurityManager.sessionManager=$sessionManager#以下为 JWT 无关配置,请忽略#声明 JdbcRealmjdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealmjdbcRealm.permissionsLookupEnabled=truejdbcRealm.authenticationQuery=SELECT password FROM user WHERE username = ?jdbcRealm.userRolesQuery=SELECT r.name FROM role r JOIN user u ON r.id = u.role_id WHERE u.username = ?jdbcRealm.permissionsQuery=SELECT a.name FROM authority a JOIN link_role_authority l ON a.id = l.authority_id JOIN role r ON r.id = l.role_id WHERE r.name = ?#设置数据库dataSource=com.alibaba.druid.pool.DruidDataSourcedataSource.driverClassName=com.mysql.jdbc.DriverdataSource.url=jdbc:mysql://localhost:3306/web?useSSL=falsedataSource.username=webdataSource.password=123456jdbcRealm.dataSource=$dataSource#指定 securityManager 的 realms 实现securityManager.realms=$jdbcRealm#设置 urlauthc.loginUrl=/loginroles.unauthorizedUrl=/unauthorizedperms.unauthorizedUrl=/unauthorized[urls]#无需用户认证/login=anon/logout=anon/unauthorized=anon/static/**=anon#需要用户认证/authenticated=authc#用户认证 + 角色验证/role=authc,roles[admin]#用户认证 + 权限验证/permission=authc,perms["user_add"]
MySimpleCookie
public class MySimpleCookie extends SimpleCookie { @Override public String readValue(HttpServletRequest request, HttpServletResponse ignored) { //读取 SessionId,即 jwt 串 String value = request.getHeader(getName()); if (value == null) value = request.getParameter(getName()); return value; }}
MySessionIdGenerator
public class MySessionIdGenerator extends JavaUuidSessionIdGenerator { static int count = 0; @Override public Serializable generateId(Session session) { //如果进行了基于 JWT 的用户认证,可以获取加密生成的 JWT 串并返回,<JWT, Session> 存入 Shiro 会话池 // SessionId 即为 JWT 串,可通过 JWT 从会话池中获取相应的会话信息 if (++count % 2 == 0) return String.valueOf(count); //如果不存在用户认证,随便返回一个值,但不能为 null return super.generateId(session); }}
index.jsp
<%@ page import="org.apache.shiro.SecurityUtils" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>首页</title></head><body><% System.out.println("会话id:" + SecurityUtils.getSubject().getSession().getId()); System.out.println("会话创建时间:" + SecurityUtils.getSubject().getSession().getStartTimestamp());%></body></html>
启动服务器,当不提供任何参数时
//可以看到不断生成新的会话会话id:ff70105d-b192-41aa-8b66-b1c5ff0e30fd会话创建时间:Sat Sep 30 00:16:45 CST 2017会话id:2会话创建时间:Sat Sep 30 00:16:46 CST 2017会话id:7228b82d-2520-4830-bb4f-d4cf450fe982会话创建时间:Sat Sep 30 00:16:56 CST 2017会话id:4会话创建时间:Sat Sep 30 00:16:56 CST 2017会话id:45f96994-3647-4aa1-8d67-a82c436c349f会话创建时间:Sat Sep 30 00:16:56 CST 2017会话id:6会话创建时间:Sat Sep 30 00:16:56 CST 2017会话id:a3eea41d-311d-407b-9e5d-7491eaf229b4会话创建时间:Sat Sep 30 00:16:57 CST 2017会话id:8会话创建时间:Sat Sep 30 00:16:57 CST 2017会话id:3f45c24f-a1ab-462c-984d-c32060213bf8会话创建时间:Sat Sep 30 00:16:57 CST 2017会话id:10会话创建时间:Sat Sep 30 00:16:57 CST 2017
提供参数,将 URL 改为 http://localhost:8080/shiro/?token=2
//可以看到会话得到维持会话id:2会话创建时间:Sat Sep 30 00:16:46 CST 2017会话id:2会话创建时间:Sat Sep 30 00:16:46 CST 2017会话id:2会话创建时间:Sat Sep 30 00:16:46 CST 2017会话id:2会话创建时间:Sat Sep 30 00:16:46 CST 2017会话id:2会话创建时间:Sat Sep 30 00:16:46 CST 2017会话id:2会话创建时间:Sat Sep 30 00:16:46 CST 2017会话id:2会话创建时间:Sat Sep 30 00:16:46 CST 2017会话id:2会话创建时间:Sat Sep 30 00:16:46 CST 2017
阅读全文
0 0
- 将 Apache Shiro 改造成 JWT 认证方式
- Apache Shiro 认证
- Apache Shiro 认证过程
- Apache Shiro 认证过程
- Apache Shiro 实现认证
- Apache Shiro 使用手册(二)Shiro 认证
- Apache Shiro 使用手册(二)Shiro 认证
- Apache Shiro 使用手册(二)Shiro 认证
- Apache Shiro 使用手册(二)Shiro 认证
- Apache Shiro 使用手册(二)Shiro 认证
- Apache Shiro 使用手册(二)Shiro 认证
- Apache Shiro 使用手册(二)Shiro 认证
- Apache Shiro 使用手册(二)Shiro 认证
- Apache Shiro 使用手册(二)Shiro 认证
- Apache Shiro 使用手册(二)Shiro 认证
- Apache Shiro 使用手册(二)Shiro 认证
- Apache Shiro(二)Shiro 认证
- Apache Shiro 使用手册(二)Shiro 认证
- 介绍一种适合多人共同开发的模式
- C语言命令行参数
- HTML5与JQuery炫酷经典实例
- 字符匹配kmp算法
- LeetCode 0053
- 将 Apache Shiro 改造成 JWT 认证方式
- python实现自动输出文字小demo(cmd下)
- 2122 数据结构实验之链表七:单链表中重复元素的删除
- java中的AES 256算法遇到 Illegal key size or default parameters错的解决办法
- !可以防止鼠标单击移动 标签 特别是动态生产的元素标签
- PAT 甲级 1048. Find Coins (25)
- 51Nod 1183 编辑距离 (DP
- Mac下配置sublime实现LaTeX
- 使用Struts,前台提交给后台的汉字为乱码