使用场景

现在很多基于restful的api接口都有个登录的设计,也就是在发起正式的请求之前先通过一个登录的请求接口,申请一个叫做token的东西。申请成功后,后面其他的支付请求都要带上这个token,服务端通过这个token验证请求的合法性。这个token通常都有一个有效期,一般就是几个小时。

比如我之前接入过一个支付宝和微信支付的通道,他们提供的api就要求先登录获取token然后才能使用支付的api接口。

在比如微信的公众平台接口,关键的接口在使用之前都要带access token。access_token是公众号的全局唯一票据,有效期为7200秒,重复获取将导致上次获取的access_token失效。

接口调用请求说明

http请求方式: GET

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
  • 1

参数说明

参数 是否必须    说明
  grant_type  是   获取access_token填写client_credential
  appid   是   第三方用户唯一凭证
  secret  是   第三方用户唯一凭证密钥,既appsecret
  返回说明

正常情况下,微信会返回下述JSON数据包给公众号:

{"access_token":"ACCESS_TOKEN","expires_in":7200}
  • 1

参数 说明
  access_token    获取到的凭证
  expires_in  凭证有效时间,单位:秒
  错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):

{"errcode":40013,"errmsg":"invalid appid"}
  • 1

什么是JWT(json web token)

首先说它是一种规范。目的是在客户端和服务端之间定义一种鉴权行为从而保证数据传递的安全性。

JWT 标准的 Token 有三个部分:

  • header
  • payload
  • signature
  • 中间用点分隔开,并且都会使用 Base64 编码,所以真正的 Token 看起来像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
  • 1

关于三个部分具体都是些什么东西,大家自行搜索即可,不是我这篇文章的重点。

我们说restful API中使用的token鉴权机制,大部分都是遵循JWT规范的,也就是底层都是对JWT的具体实现。

一个java实现实例

说了这么多,该上实例了。这个实例会用到redis,spring等技术。

这个实例原出处:

RESTful登录设计(基于Spring及Redis的Token鉴权)

原项目是基于maven的。我这里为了调试方便把项目迁移到myeclipse中,关于如何导入到myeclipse中,请参考:

如何在myeclipse中配置,导入maven项目

上面的链接中对代码解释的也比较清楚了。我这里只说下如何运行测试效果。

根据本地实际情况修改mysql和redis配置

这个工程其实是个基于spring boot的项目,Spring boot 的默认配置文件是 resources 下的 application.properties。所以我们主要是修改它。

其中spring.datasource.*的配置项是mysql相关的,这里解释下。有人可能有疑问为什么程序里并没有看到引用这些配置变量。这是因为spring boot是一种约定优于配置的开发框架。比如,

spring.datasource.username就是表示数据库用户名,你不能随便改,框架里就用它作为查抄依据。

同理spring.redis.*也是redis相关的配置。

上面几个地方要根据你本地实际情况修改。修改完之后,在你的mysql中新建一个名为demo的数据库(如果原来没有的话)。然后执行工程中init.sql中的语句,这是为了初始化表。

运行

首先执行右键项目目录,run as -> maven install,会看到类似下面的输出:

然后再执行 run as -> java application, 然后选择程序的入口:

同样看下console有没有错误,如果报错通常是上面的配置不对,仔细检查下。

打开浏览器,输入http://localhost:8080,显示如下:

表明运行成功。

测试下登录,

登录成功,并且也成功的创建了token。

退出登录,在authorization中填写用userId和token以”_”拼接得到的字符串。

有人会问为什么authorization需要这样的格式才能退出登录成功。下面的代码可以说明问题,

...
@RequestMapping(method = RequestMethod.DELETE)
@Authorization
public ResponseEntity logout(@CurrentUser User user) {
tokenManager.deleteToken(user.getId());
return new ResponseEntity<>(ResultModel.ok(), HttpStatus.OK);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

@Authorization用于表示该操作需要登录后才能进行,否则会返回401错误。如下:

...
//验证token
TokenModel model = manager.getToken(authorization);
if (manager.checkToken(model)) {
//如果token验证成功,将token对应的用户id存在request中,便于之后注入
request.setAttribute(Constants.CURRENT_USER_ID, model.getUserId());
return true;
}
//如果验证token失败,并且方法注明了Authorization,返回401错误
if (method.getAnnotation(Authorization.class) != null) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

为了验证redis的缓存有效期,我把代码做了一点修改,过期时间设置成1分钟便于测试。

/**
* token有效期(分钟)
*/
public static final int TOKEN_EXPIRES_MINS = 1; public TokenModel createToken(long userId) {
//使用uuid作为源token
String token = UUID.randomUUID().toString().replace("-", "");
TokenModel model = new TokenModel(userId, token);
//存储到redis并设置过期时间
// redis.boundValueOps(userId).set(token, Constants.TOKEN_EXPIRES_HOUR, TimeUnit.HOURS); redis.boundValueOps(userId).set(token, Constants.TOKEN_EXPIRES_MINS, TimeUnit.MINUTES);
return model;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

然后我先登录,等超过一分钟再退出登录,确认会返回401错误。

# RESTful登录(基于token鉴权)的设计实例的更多相关文章

  1. 全栈项目|小书架|微信小程序-登录及token鉴权

    小程序登录 之前也写过微信小程序登录的相关文章: 微信小程序~新版授权用户登录例子 微信小程序-携带Token无感知登录的网络请求方案 微信小程序开通云开发并利用云函数获取Openid 也可以通过官方 ...

  2. 关于防范csrf攻击基于token鉴权

    在web开发中,之前都使用cookie + session方式来实现身份认证鉴权.但是现在前后端分离,以及终端有可能不支持cookie的情况下,一般都采用token方式.现在系统设计思路如下: 服务端 ...

  3. 如何在SpringBoot中集成JWT(JSON Web Token)鉴权

    这篇博客主要是简单介绍了一下什么是JWT,以及如何在Spring Boot项目中使用JWT(JSON Web Token). 1.关于JWT 1.1 什么是JWT 老生常谈的开头,我们要用这样一种工具 ...

  4. Postman 关联接口测试(带有token鉴权)

    Postman 关联接口测试(带有token鉴权) 一.登陆接口 创建一个request请求 在Tests中添加JavaScript代码,用来获取鉴权 pm.test("V2", ...

  5. RESTful登录设计(基于Spring及Redis的Token鉴权)

    转载自:http://www.scienjus.com/restful-token-authorization/ http://m.blog.csdn.net/article/details?id=4 ...

  6. shiro,基于springboot,基于前后端分离,从登录认证到鉴权,从入门到放弃

    这个demo是基于springboot项目的. 名词介绍: ShiroShiro 主要分为 安全认证 和 接口授权 两个部分,其中的核心组件为 Subject. SecurityManager. Re ...

  7. Python接口自动化基础---token鉴权

    有些登录使用cookie,有些登录需要token验证,token传参一般有两种形式,一种是在请求头中,一种是使用URL传参 这里举例说明一下请求头中的token方式: #登录 param1={'use ...

  8. token鉴权的一种实现方式图解

  9. Session, Token, OAuth 鉴权那些事儿

    鉴权那些事 整体思路 无论什么样的服务, Web 服务总是不能绕开鉴权这个话题的, 通过有效的鉴权手段来保护网站数据, 来为特定用户提供服务. 整体来说, 有三种方式: Session-Cookie ...

随机推荐

  1. Javascript之hoisting变量提升

    javascript不仅仅是一门弱类型语言,还是一门解释型语言.一门编程语言的本质就是这样,优点即是缺点,缺点也往往是优点.JS因为有了变量提升,能够使我们在编程时可以忽略“先声明,再使用”的规则,但 ...

  2. PostgreSQL 数据库备份与恢复 pd_dump pg_restore

    备份 PG 数据库生成的文件可以有两种,一种是 SQL 文件,一种是二进制文件,二进制文件只能使用 pg_restore 进行恢复. PostgreSQL 数据库操作简要说明 PostgreSQL数据 ...

  3. seekBar拖动滑块

    中秋节学习,, 通过拖动滑块,改变图片的透明度 <?xml version="1.0" encoding="utf-8"?> <LinearL ...

  4. Z-Score数据标准化(转载)

    简介Z-Score标准化是数据处理的一种常用方法.通过它能够将不同量级的数据转化为统一量度的Z-Score分值进行比较. 一句话解释版本: Z-Score通过(x-μ)/σ将两组或多组数据转化为无单位 ...

  5. QVector init error

    QMetaType::registerType: Binary compatibility break -- Size mismatch for type 'PtsData' [1025]. Prev ...

  6. Qt编写气体安全管理系统12-设备双击

    一.前言 在编写这个项目的过程中,有个得到客户夸赞的小功能就是,设备按钮双击,在离线的时候是双击重连设备,在线的时候是双击弹出具体详情界面,回控设备,参数设置等.在modbus设备通信过程中,设定了超 ...

  7. k8s记录-dockerfile

    FROM 代表基于哪个镜像 RUN 安装软件使用 MAINTAINER 镜像的创建者 CMD 容器启动时执行的命令,但是一个Dockerfile中只能有一条CMD命令,多条则只执行最后一条CMD EN ...

  8. k8s记录-etcd集群部署(三)

    https://blog.csdn.net/fy_long/article/details/86542872 1)程序准备tar xvf etcd-v3.3.11-linux-amd64.tar.gz ...

  9. Laya的动画制作,整图动画,序列图动画,时间轴动画,龙骨动画

    参考: Laya动画基础 Egret帧动画工具类 版本:2.1.1.1 序列图动画 白鹭的序列图动画,使用TexureMerger合图,然后使用MovieClip类播放. Laya的话,使用图集打包工 ...

  10. 如何发布自定义的UI 组件库到 npmjs.com 并且编写 UI组件说明文档

    记录基于 antd 封装业务组件并发布到npm 上的过程:(TS + React + Sass) 初始化项目: 1.yarn create react-app winyhui --typescript ...