校验令牌
Get: http://localhost:40400/auth/oauth/check_token?token=
响应结果:
该 接 口 请 求 会 重 新 调 用 U s e r D e t a i l s S e r v i c e I m p l 类 中 的 l o a d U s e r B y U s e r n a m e 方 法 。 \color{#FF0000}{该接口请求会重新调用UserDetailsServiceImpl类中的loadUserByUsername方法。}该接口请求会重新调用UserDetailsServiceImpl类中的loadUserByUsername方法。
刷新令牌
刷新令牌是当令牌快过期时重新生成一个令牌,它和授权码跟密码模式生成令牌不同,刷新令牌是取授权码跟密码模式生成的令牌结果集重新生成一个令牌,只需要一个刷新令牌、客户端id和客户端密码。
Post:http://localhost:40400/auth/oauth/token
参数:
grant_type: 固定为 refresh_token
refresh_token:填写申请令牌中的refresh_token字段值
刷新令牌成功,会重新生成新的访问令牌和刷新令牌,令牌的有效期也比旧令牌长。
刷新令牌通常是在令牌快过期时进行刷新,让客户登录时间延长,不用让用户重新登录。
JWT研究
传统授权方法的问题是用户每次请求资 源 服 务 \color{#FF0000}{资源服务}资源服务,资源服务都需要携带令牌访问认 证 服 务 \color{#FF0000}{认证服务}认证服务去校验令牌的合法性,并根据令牌获取用户的相关信息,性能低下。
使用JWT的思路是,用户认证通过会得到一个JWT令牌,JWT令牌中已经包括了用户相关的信息,客户端只需要携带JWT访问资源服务,资源服务根据事先约定的算法自行完成令牌校验,无需每次都请求认证服务完成授权。
J W T 令 牌 就 是 为 了 解 决 不 用 每 次 请 求 认 证 服 务 完 成 授 权 。 \color{#FF0000}{JWT令牌就是为了解决不用每次请求认证服务完成授权。}JWT令牌就是为了解决不用每次请求认证服务完成授权。
JWT令牌授权过程如下图:
什么是JWT?
JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简洁的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公钥/私钥对来签名,防止被篡改。
JWT令牌的优点:
1、JWT基于json,非常方便解析。
2、可以在令牌中自定义丰富的内容,易扩展。
3、通过非对称加密算法及数字签名技术,JWT防止篡改,安全性高。
4、资源服务使用JWT可不依赖认证服务即可完成授权。
缺点:令牌较长,存储空间比较大
令牌结构
通过学习JWT令牌结构为自定义JWT令牌打好基础。
JWT令牌由三部分组成,每部分中间使用点(.)分隔,比如:xxxxx.yyyyy.zzzzz
1、Header
包括令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA)
例如:
{ "alg": "HS256", "typ": "JWT" }
将上边的内容使用Base64Url编码,得到一个字符串就是JWT令牌的第一部分。
2、Payload
第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存放jwt提供的现成字段,比 如:iss(签发者),exp(过期时间戳), sub(面向的用户)等,也可自定义字段。
此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。
最后将第二部分负载使用Base64Url编码,得到一个字符串就是JWT令牌的第二部分。
{ "sub": "1234567890", "name": "456", "admin": true }
3、Signature
第三部分是签名,此部分用于防止jwt内容被篡改。
这个部分使用base64url将前两部分进行编码,编码后使用点(.)连接组成字符串,最后使用header中声明 签名算法进行签名。
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
base64UrlEncode(header):jwt令牌的第一部分。
base64UrlEncode(payload):jwt令牌的第二部分。
secret:签名所使用的密钥。
JWT入门
本节我们使用Spring Security 提供的JwtHelper来创建JWT令牌,校验JWT令牌等操作。
生成私钥和公钥
JWT令牌生成采用非对称加密算法
1、生成密钥证书
下边命令生成密钥证书,采用RSA 算法每个证书包含公钥和私钥
keytool -genkeypair -alias xckey -keyalg RSA -keypass xuecheng -keystore xc.keystore -storepass xuechengkeystore
在桌面创建文件夹jwt,cmd进入该目录,输入上面指令:
查询证书信息: keytool -list -keystore xc.keystore
口令输入:xuechengkeystore
删除别名:keytool -delete -alias xckey -keystore xc.keystore
2、导出公钥
openssl是一个加解密工具包,这里使用openssl来导出公钥信息。
安装 openssl:http://slproweb.com/products/Win32OpenSSL.html
配置openssl的path环境变量,本教程配置在D:\Soft\OpenSSL-Win64\bin
cmd进入xc.keystore文件所在目录执行如下命令:
keytool ‐list ‐rfc ‐‐keystore xc.keystore | openssl x509 ‐inform pem ‐pubkey
将上边的公钥拷贝到文本文件中,合并为一行放到publickey.txt文件中。
1、生成jwt令牌
执行TestJwt类中的testCreateJwt方法生成密钥:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoieGh5In0.Y5wtZJAlirAMtQ2qQaNehDDa1uBhHWjJAHeNBXYcKP48rYpdM--oMGXZJgMa56HgXJ29YUtdKJstO8NUqJXLp7GkUvXWDBwhvmlyT82Vci7pwJitgO6YCBaYcXOSUFmWHxDX6o5RrJ0ivfU0nBE07FX30k0eBvDYnxH5FVRqo19WMBR9a36bHcYBrj9ZWsinbOmMUCgLMkNnteXHXPPH7PqTTpAmn_8C5cGQS8ER3CXXlSmRrGSn8uoYQKV87W_x7mapu6lb7vYLgVyBTOH2jUduOYg7rOD4S5JC7XJFvuyEH4z1Mew1k5NqoBBx5dhsRDJFANxoqvQpIlDbwJ1gzg
2、验证jwt令牌
执行TestJwt类中的testVerify方法进行校验
校验成功返回令牌的名字:
认证接口开发
用户登录的流程图如下:
Redis配置
1、安装Redis服务
2、安装redis-desktop-manager客户端
pom文件中添加redis
3、redis连接配置
在xc-service-ucenter-auth工程的yml文件中配置如下:
spring: application: name: xc-service-ucenter-auth redis: host: ${REDIS_HOST:127.0.0.1} port: ${REDIS_PORT:6379} timeout: 5000 #连接超时 毫秒 jedis: pool: maxActive: 3 maxIdle: 3 minIdle: 1 maxWait: -1 #连接池最大等行时间 -1没有限制
4、测试
执行RedisTest类中的testRedis方法:
返回结果,说明执行成功:
认证服务
1、登录接口
前端post提交账号、密码等,用户身份校验通过,生成令牌,并将令牌存储到redis。 将令牌写入cookie。
2、退出接口
校验当前用户的身份是否合法并且为已登录状态。 将令牌从redis删除。 删除cookie中的令牌。
流程:
1、api中的方法:
在AuthControllerApi类中添加login和logout方法;
2、yml文件中配置:
auth: tokenValiditySeconds: 1200 #token存储到redis的过期时间 clientId: XcWebApp clientSecret: XcWebApp cookieDomain: xuecheng.com cookieMaxAge: -1
3、申请令牌
为了不破坏Spring Security的代码,我们在Service方法中通过RestTemplate请求Spring Security所暴露的申请令牌接口来申请令牌。
执行TestClient类中的testClient方法测试;
4、Dao
暂时使用静态数据,待用户登录调通再连接数据库校验用户信息。
5、Service
调用认证服务申请令牌,并将令牌存储到 redis。
1、AuthToken
创建 AuthToken模型类,存储申请的令牌,包括身份令牌、刷新令牌、jwt令牌
身份令牌:用于校验用户是否认证
刷新令牌:jwt令牌快过期时执行刷新令牌
JWT令牌:用于授权。
6、Controller
在AuthController中添加、saveCookie、logout方法
登录url放行
认证服务默认都要校验用户的身份信息,这里需要将登录url放行
在WebSecurityConfig类中重写 configure(WebSecurity web)方法,如下:
@Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/userlogin","/userlogout","/userjwt"); }
测试认证接口:
Post请求:http://localhost:40400/auth/userlogin
测试结果:
测试写入Cookie
cookie最终会写到xuecheng.com域名下,可通过nginx代理进行认证,测试cookie是否写成功。
1、配置nginx代理
在server中添加配置代理路径:
#认证 location ^~ /openapi/auth/ { proxy_pass http://auth_server_pool/auth/; }
添加:
#认证服务 upstream auth_server_pool{ server 127.0.0.1:40400 weight=10; }
POST:http://ucenter.xuecheng.com/openapi/auth/userlogin
观察cookie写入结果:
这个value就是返回值返回的短令牌