摘要:本文讨论一个问题:存储token时,token与对应用户id谁来作为key? 问题起源问题起源于要给公司的后台管理系统添加权限管理,选用的是开源框架shiro,而原本系统上是采用token做了登录校验的。

本文分享自华为云社区《讨论两种Redis中Token的存储方式》,作者:洛叶飘。

问题起源

问题起源于要给公司的后台管理系统添加权限管理,选用的是开源框架shiro,而原本系统上是采用token做了登录校验的。

我所采用的shiro验证方式是,每次接口请求,根据token来获取用户id,然后通过shiro中的登录验证机制来进行权限校验。因此,“根据token获取用户id”就要求在存储用户token时,以token为键值key,以用户ID为value值。

然而此时面临一个问题是,系统原本的token存储方式如下,我们称之为第一种:用户ID为key。

cache.set(TOKEN_PREFIX + userid, token);

这就需要我做出判断,需不需要修改token的存储方式为下面的形式:我们称之为第二种:token为key。

cache.set(TOKEN_PREFIX + token, userid);

思考

第一个问题,两种方式是否都能够实现需求功能?

我们需要实现的功能包括:

  1. 登录验证
  2. shiro中的权限验证

登录验证

对于"用户ID为key"的方式,需要前端传递用户id+token两个值,验证登录状态需要我们根据前端传递的用户ID,获取数据库中存储的token,与前端传递的token进行校验,如果一致,则校验通过,否则返回错误信息,提示用户需要重新登录等等。

对于“token为key”的方式,前端至少需要传递token一个值,根据前端传递的token,获取数据库中存储的用户ID,如果能获取到,则校验通过,否则提示用户token已过期,需要用户重新登录等等。

shiro中的权限验证

shiro中的权限验证,涉及到具体的实现机制,以token为key的方式,就以我们的真实实现为例:

// shiro登录代码:
Subject s = SecurityUtils.getSubject();
JWTToken jwtToken = new JWTToken(token);
subject.login(jwtToken);
// 实现AuthenticationToken的类:
import org.apache.shiro.authc.AuthenticationToken; public class JWTToken implements AuthenticationToken {
private static final long serialVersionUID = 1L; // 密钥
private String token; public JWTToken(String token) {
this.token = token;
} @Override
public Object getPrincipal() {
return token;
} @Override
public Object getCredentials() {
return token;
}
} /**
* 自定义的登录验证类:
*/
public class ShiroDbRealm extends AuthorizingRealm{
/**
* 重写shiro的token
*/
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JWTToken;
} /**
* 角色,权限认证
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//这里可以连接数据库根据用户账户进行查询用户角色权限等信息
return simpleAuthorizationInfo;
} /**
* 自定义认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
String token = (String) auth.getCredentials();
// 解密获得userid,用于和数据库进行对比
// getUserId实际就是通过token,在数据库中取对应的userid
Integer userid = JwtUtils.getUserId(token);
if (tuserid == null) {
throw new AuthenticationException("token 校验失败");
}
return new SimpleAuthenticationInfo(token, token, getName());
}
}

如果采用userid为key的方式,不难实现,也修改其实现方式,

第二个问题,两种方式哪一种传输的数据量更少?

第一种方式需要前端每次请求都传递token+userid;而第二种实际上可以只传递token,后台根据token解密(或数据库查找)来获取用户信息。

第三个问题,两种方式哪种更安全?

两种方式的安全应该是一样的,核心是后台通过数据库保存token与userid的对应信息。

个人意见

个人比较细化第二种,以token为key的方式,首先,前端传递简单,只需要传递token即可;二是后端通过这种方式,可以统一当前登录人的获取方式,而不是每次在接口中获取header中的用户id。

点击关注,第一时间了解华为云新鲜技术~

讨论两种Redis中Token的存储方式的更多相关文章

  1. Android笔记——Android中数据的存储方式(一)

    Android中数据的存储方式 对于开发平台来讲,如果对数据的存储有良好的支持,那么对应用程序的开发将会有很大的促进作用. 总体的来讲,数据存储方式有三种:一个是文件,一个是数据库,另一个则是网络.其 ...

  2. Android笔记——Android中数据的存储方式(二)

    我们在实际开发中,有的时候需要储存或者备份比较复杂的数据.这些数据的特点是,内容多.结构大,比如短信备份等.我们知道SharedPreferences和Files(文本文件)储存这种数据会非常的没有效 ...

  3. C语言中float,double类型,在内存中的结构(存储方式)

    C语言中float,double类型,在内存中的结构(存储方式)从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float是32位的,double是64位的,所以doubl ...

  4. Android ListView两种长按弹出菜单方式

    转自:http://www.cnblogs.com/yejiurui/p/3247527.html package com.wyl.download_demo; import java.util.Ar ...

  5. 原码,补码,反码的概念及Java中使用那种存储方式

    原码,补码,反码的概念及Java中使用那种存储方式: 原码:原码表示法是机器数的一种简单的表示法.其符号位用0表示正号,用:表示负号,数值一般用二进制形式表示 补码:机器数的补码可由原码得到.如果机器 ...

  6. 两种不同的扩展Scrum的方式

    两种不同的扩展Scrum的方式 1.LeSS和LeSS Huge –大型Scrum LeSS(和LeSS Huge –真正的大型程序)的合著者Craig Larman首先批评了管理,开发人员和客户传统 ...

  7. Matlab中数据的存储方式

    简介 MATLAB提供了丰富的算法以及一个易于操作的语言,给算法研发工作者提供了很多便利.然而MATLAB在执行某些任务的时候,执行效率偏低,测试较大任务量时可能会引起较长时间的等待.未解决这个问题, ...

  8. 两种Redis持久化原理的详解

    Redis为持久化提供了两种方式: RDB:在指定的时间间隔能对你的数据进行快照存储. AOF:记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据. 本文将通过下面内容的介 ...

  9. Jwt 中 token应该存储到哪里?

    关于 token 的存储问题 JWT: csrf 攻击无法获取第三方的 cookie,而是直接使用 cookie进行查询的时候会自动携带 cookie. xss攻击通过代码注入可以获取 cookie. ...

随机推荐

  1. Leetcode刷题之链表增加头结点的前缀节点

    链表之增加头结点的前缀节点 在许多链表题中往往需要在题目给的头结点之前增加一个前缀节点 通常在删除链表和头结点需要交换时需要用到这一操作 因为增加这个节点就避免了对删除头结点这种特殊情况的特殊处理 而 ...

  2. (stm32f103学习总结)—can总线

    参考:CAN总线的位时序与参数设置 CAN总线位同步 1 CAN总线介绍 CAN 是Controller Area Network 的缩写,中文意思是控制器局域网 络,是ISO国际标准化的串行通信协议 ...

  3. 《剑指offer》面试题2:实现Singleton 模式

    面试题2:实现Singleton 模式 题目:设计一个类,我们只能生成该类的一个实例.   只能生成一个实例的类是实现了Singleton (单例)模式的类型.由于设计模式在面向对象程序设计中起着举足 ...

  4. 前端入门-day2(常见css问题及解答)

    写在前面 今天是入门前端的day2, 小伙伴们应该已经看了一些HTML的基础和CSS的基础了,是不是遇到了很多关于CSS的问题呢.因为HTML很少有太复杂的问题,所以直接写一篇关于CSS的常见问题及解 ...

  5. ES6-11学习笔记--正则表达式的扩展

    y修饰符 u修饰符   复习以前的修饰符: i(忽略大小写) m(多行匹配) g(全局匹配)   y修饰符:粘连修饰符 const str = 'aaa_aa_a' const reg1 = /a+/ ...

  6. Java中if else条件判断语句的执行顺序

    学习目标: 掌握 if else 条件判断的使用 学习内容: 1.if语法 if(boolean表达式) { 语句体; } if后面的{}表示一个整体-代码块,称之为语句体,当boolean表达式为t ...

  7. Java 实例 - 读取文件内容

    原文作者:菜鸟教程 原文链接:Java 实例 - 读取文件内容(建议前往原文以获得最佳体验) 按行读取文本文件 import java.io.*; public class Main { public ...

  8. Java报错:Failed to execute goal org.eclipse.jetty:jetty-maven-plugin:9.4.26.v20200117:run (default-cli) on project ssm-mybatis-plus: Failure

    修改一下端口就好了,不要用80端口. <plugin> <groupId>org.eclipse.jetty</groupId> <!--嵌入式Jetty的M ...

  9. 攻防世界——gif

    分析 只有黑白两种颜色,大小均一样.考虑代表着二进制. python脚本 ''' 同样颜色的图片的二进制数据都相同 编写思路:取二进制 -> 转ascii码 ''' white = open(r ...

  10. toString()函数与valueOf()函数

    一.前言 在等于运算符中,如果比较的内容包含对象类型数据,则会涉及隐式转换,那么就会调用toString()函数和valueOf()函数,下面我们将会了解到关于这两个函数的基本概念和使用场景. 二.t ...