上手第一步先整个登录模块,找资料做个优化,感觉找来博客写的很杂乱,原理写的非常冗长,完了用法说的的不清不楚的。自己总结一下,也顺便巩固。
兄弟萌,如果感觉写得好的话,给个赞再叉呗~~
参考:
https://blog.csdn.net/weixin_46073538/article/details/128641746
https://www.cnblogs.com/kirito-c/p/12402066.html
https://blog.csdn.net/u014553029/article/details/112759382
登录情况分析
以往登录是为了验证身份,完了之后享受服务。但这样的话,只会在一开始验证一下,之后就不会进行验证了。这显然有问题。如果直接绕过登录模块,那么后续依旧可以享受服务。
第一个解决方案,次次享受服务都要验证登录。这显然很蠢。
所以,这时候就有了“token”解决方案。也就是在服务端生成一个token,在后续客户端想要享受服务,都需要携带这个token来证明我的身份。
这样的好处是,我后面都不需要验证身份,只用这个token来代表我的身份。
但这样衍生出了新的问题:我怎么保护这个token?。因为现在这个token就是代表了我的身份,如果token一旦泄露,相当于别人知道了我的账号密码,可以享受服务。
对称加密与非对称加密
密码学中对称加密:加密算法是公开的,靠的是秘钥来加密数据,使用一个秘钥加密,必须使用相同的秘钥才解密。
非对称加密:加密和解密使用不同的秘钥,一把公开的公钥,一把私有的私钥。公钥加密的信息只有私钥才能解密,私钥加密的信息只有公钥才能解密。
e.g. RSA(非对称)
套入具体环境,所有客户端都作为加密方,服务端作为解密方,那么一个客户端针对密码加密,就只能让服务端解密,其余任何客户端都无法解密。
而实现方式一般是公私密钥。
使用公钥进行加密,只能用私钥进行解密,使用私钥加密,只能使用公钥解密。
所以一般传输密码时候,密码使用公钥加密,传到服务器进行解密。
JWT
上面说到最重要的就是这个token,JWT就是用来生成这个token的。
首先说一下JWT最终生成的token结构:
-
Header:存储的是关于这个JWT token的元数据信息。可以简单认为就是一个config信息。里面最重要的就是存储签名所使用的编码格式。
-
载荷:是一个JSON对象,里面存一些有效信息,可以自己定义。但是不能存储重要信息
-
签名:这个是最重要的,目前先认为他是一个简单的hash结果先。
整个过程是:
- header与载荷部分进行BASE64编码
- 然后将header与载荷进行base64编码之后的结果与一个secret进行加密获得签名
- 最后将三个部分以点(.)进行连接,也就是最后的token。
- 首先注意,header与载荷都是简单使用base64编码,这个是任何人都可以解码,目的只是为了更好传传输除了英文字母以外的字符。所以在载荷里面绝对不能加重要的信息
- 再仔细想,如果我仅有前两个个,随随便便就能够伪造,所以我还需要第三部分签名。所以签名是最重要的,因为他要被难以伪造!但他如何实现难以伪造,就是因为用的加密算法。一般在单服务器环境下使用的是HS256加密,这个是一种对称加密,所以只有获得secret才能解密。
所以jwt中签名是最重要的,而签名之中secret是最重要的。
java实现
实现过程:
- 写header
- 写载荷
- 加密算法+secret构造一下签名就行。
但如果用一下jjwt就简单些,直接构造一下header载荷,完了说明一下加密算法以及密钥就行。
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.12.3</version></dependency>
long expireTime = System.currentTimeMillis() + 86400000;String token = Jwts.builder()// 设置头部信息header.header().add("typ", "JWT").add("alg", "HS256").and()// 设置自定义负载信息payload.claim("username", username)// 令牌ID//.id(uuid)// 过期日期.expiration(new Date(expireTime))// 签发时间.issuedAt(new Date())// 主题.subject(SUBJECT)// 签发者.issuer(JWT_ISS)// 签名.signWith(Keys.hmacShaKeyFor("secret fill in this place".getBytes()), Jwts.SIG.HS256).compact();
这个写的比较简陋,能用就行嘿嘿,后面再补
最关键的就是加密算法、secret以及时间设置,其他的自己DIY就行。