如何设计安全可靠的开放接口---之Token

【如何设计安全可靠的开放接口】系列

1. 如何设计安全可靠的开放接口—之Token
2. 如何设计安全可靠的开放接口—之AppId、AppSecret
3. 如何设计安全可靠的开放接口—之签名(sign)
4. 如何设计安全可靠的开放接口【番外篇】—关于MD5应用的介绍
5. 如何设计安全可靠的开放接口—还有哪些安全保护措施
6. 如何设计安全可靠的开放接口—对请求参加密保护
7. 如何设计安全可靠的开放接口【番外篇】— 对称加密算法

前言

Open API是会暴露到公网被访问的接口,那与内网接口最重要的区别就是如何做好安全的问题,常见的安全问题有:合法身份判别、数据防窥、数据防篡改、请求防重放、Dos攻击等等,本文先来看看对于合法身份判别这个问题是如何解决的。

一、Token机制

Token自然是非常好的选择,客户端成功登陆后,服务端就会生成一个Token返回给客户端,之后客户端每次请求只需要带上这个Token即可表明身份,解决了每次登陆的问题(Http是无状态通信协议)。

1. Token生成

关于Token的生成最常见的方式就是使用JWT(JSON Web Token),早期要说解决每次登陆的问题,通过Session就可以做到,那为什么又出现了JWT呢?

我们先来看看使用Session实现的方式

  1. 用户在客户端输入账号、密码。
  2. 服务端验证账号、密码正确后,获取当前session,并在session里面保存需要的数据。
  3. 服务器像客户端返回一个session_id,并将此写入客户端Cookie中。
  4. 之后用户每次在客户端的请求都会从Cookie中把session_id带给服务端。
  5. 服务端只需要根据session_id匹配到之前保存在session里面的数据即可。

2. Session存在的问题

session这种方式最大的问题就是需要服务端保存数据,如果要做跨域访问、集群访问就需要每台服务器都能同步到session信息,当然你可以通过一些分布式的组件来持久化session,但在跨域访问中依然比较棘手,而且代价也较高。

3. JWT是如何解决Session存在的问题的

既然服务端保存session必然存在数据同步的问题,那就干脆不要保存了,这就是JWT的做法,数据只会记录在客户端,当验证完用户的账号、密码后,JWT会生成一种约定好的格式数据,然后服务端把这份数据发送给客户端,客户端之后每次请求带上这份数据即可,JWT自然能够对其进行验证,这样一来,服务端就从有状态变成无状态了,也就能轻松的实现扩展了。

二、JWT中的数据结构

JWT中的数据主要由三部分组成,分别是Header、Payload、Signature

原始数据
在这里插入图片描述

加密后
在这里插入图片描述

三部分数据用'.'隔开

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoieGlhb21pbmciLCJpZCI6MTIzNDUsImV4cCI6MTY1MjA5ODczNX0.7WRvMdrILoSkic1uUhg34Xj31XI0ok4Lrd6qEC99Abg

1. Header

Header通常由两部分组成,例如:

{
  "typ": "JWT",
  "alg": "HS256"
}

"typ": "JWT"令牌类型,即JWT。
"alg": "HS256"使用的签名算法。

2. Payload

Payload是用来存放实际需要保存数据的地方,其中JWT官方也定义了一些字段

在这里插入图片描述
这些字段并不是强制性的,官方只是建议使用,当然你也可以自己定义各种字段,但一定要注意命名规范,避免冲突。

需要额外注意的是,保存在Payload中的信息默认是没有加密的,前面看到的数据只是签名后的结果,签名只能防止数据被篡改,所以,除非是做了二次加密,否则就不能把隐私信息放到Head或者Payload中。

3. Signature

Signature是对前面两部分数据的签名,用于验证数据没有被篡改,签名后的数据就变成如下这样:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoieGlhb21pbmciLCJpZCI6MTIzNDUsImV4cCI6MTY1MjA5ODczNX0.7WRvMdrILoSkic1uUhg34Xj31XI0ok4Lrd6qEC99Abg

三、JWT的工作方式

服务端生成Token后,一般可以保存在HTTP的请求头的Authorization字段中

在这里插入图片描述

四、JWT的使用

引入jar包

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.19.2</version>
</dependency>

1. 生成Token

public static void main(String[] args) {
    String token = createToken();
    System.out.println(token);
}

private static String createToken() {
    try {
        Algorithm algorithm = Algorithm.HMAC256("secret");
        return JWT.create()
                .withIssuer("admin")
                .withClaim("name", "xiaozhang")
                .withClaim("id", 12345)
                .sign(algorithm);
    } catch (JWTCreationException e) {
        e.printStackTrace();
    }
    return null;
}

在这里插入图片描述

在这里插入图片描述

2. token验证

public static boolean verifyToken(String token) {
    try {
        Algorithm algorithm = Algorithm.HMAC256("secret"); //use more secure key
        JWTVerifier verifier = JWT.require(algorithm)
                .withIssuer("admin")
                .withClaim("name", "xiaozhang")
                .withClaim("id", 123456) // 把id由原来的12345修改为123456
                .build();
        verifier.verify(token);
    } catch (JWTVerificationException e) {
        e.printStackTrace();
        return false;
    }
    return true;
}
com.auth0.jwt.exceptions.InvalidClaimException: The Claim 'id' value doesn't match the required one.
	at com.auth0.jwt.JWTVerifier.assertValidClaim(JWTVerifier.java:397)
	at com.auth0.jwt.JWTVerifier.verifyClaimValues(JWTVerifier.java:349)
	at com.auth0.jwt.JWTVerifier.verifyClaims(JWTVerifier.java:315)
	at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:300)
	at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:283)
	at token.TokenDemo.verifyToken(TokenDemo.java:28)
	at token.TokenDemo.main(TokenDemo.java:16)
false

3. token解析

private static Map<String, Claim> decodeToken(String token) {
    DecodedJWT jwt = JWT.decode(token);
    return jwt.getClaims();
}
{iss="admin", name="xiaozhang", id=12345}

4. 带过期时间的Token

LocalDateTime plus = LocalDateTime.now().plus(3, ChronoUnit.SECONDS);
Date expiresAt = Date.from(plus.atZone(ZoneId.systemDefault()).toInstant());
System.out.println("expiresAt: " + expiresAt);
String expiresToken = createToken(expiresAt);
Thread.sleep(4000);
System.out.println("expiresToken: " + verifyToken(expiresToken));
private static String createToken(Date expiresAt) {
    try {
        Algorithm algorithm = Algorithm.HMAC256("secret
        return JWT.create()
                .withIssuer("admin")
                .withClaim("name", "xiaozhang")
                .withExpiresAt(expiresAt)
                .withClaim("id", 12345)
                .sign(algorithm);
    } catch (JWTCreationException e) {
        e.printStackTrace();
    }
    return null;
}
expiresAt: Mon May 09 20:52:20 CST 2022
com.auth0.jwt.exceptions.TokenExpiredException: The Token has expired on Mon May 09 20:52:20 CST 2022.
	at com.auth0.jwt.JWTVerifier.assertDateIsFuture(JWTVerifier.java:420)
	at com.auth0.jwt.JWTVerifier.assertValidDateClaim(JWTVerifier.java:411)
	at com.auth0.jwt.JWTVerifier.verifyClaimValues(JWTVerifier.java:331)
	at com.auth0.jwt.JWTVerifier.verifyClaims(JWTVerifier.java:315)
	at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:300)
	at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:283)
	at token.TokenDemo.verifyToken(TokenDemo.java:72)
	at token.TokenDemo.main(TokenDemo.java:39)
expiresToken: false
  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
WP-REST-API 是WordPress 的一种接口,它通过提供标准化的RESTful API,允许开发人员使用HTTP请求来访问和操作WordPress站点的内容和数据。通过这个接口,开发人员可以使用不同的编程语言和技术来与WordPress进行交互,从而使得开发更加灵活和自由。 JWT(JSON Web Token)是一种用于认证和授权的开放标准。它通过将用户信息和权限信息编码成一种加密的令牌,以实现跨服务器和跨域的身份验证。JWT 是由三部分组成的:头部、负载和签名。头部包含令牌的加密算法和类型信息,负载包含用户的相关信息,签名用于验证令牌的真实性和完整性。 WP-REST-API JWT整合了WordPress的REST API和JWT的认证机制,使得在使用WP-REST-API进行开发的过程中,可以增加身份验证和授权的功能。它允许开发人员在请求WordPress REST API时,通过在请求头或参数中提供有效的JWT令牌来验证用户的身份和权限,并根据令牌中的负载信息来进行授权。 WP-REST-API JWT的使用具有很多优势。首先,它提供了一种轻量级的身份验证方式,减少了开发的复杂性。其次,通过JWT令牌的机制,可以实现无状态的认证和授权,提高了性能和可扩展性。此外,JWT还提供了一种可靠的机制来防止伪造和篡改请求数据,增强了系统的安全性。 总而言之,WP-REST-API JWT为开发人员提供了一种方便、灵活和安全的方式来使用WordPress的REST API。它简化了身份验证和授权的过程,并通过使用JWT令牌提高了系统的性能和安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码拉松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值