SSO单点登录
什么是单点登录
SSO(Single Sign On)
在多系统架构中,用户只需要一次登录就可以无需再次登录(比如你在打开淘宝之后点击里边的天猫)
在以前我们的单系统中,用户如果登录多个服务需要多次登录,实现单点登录之后,可以实现一次登录,全部登录!一次注销,全部注销
原理图
用户不需要重复登录192.168.1.* 只需要通过认证系统登录一次即可访问全部内容
实现原理(这里拿token作图)
实现方案
Cookie方案
用cookie作为媒介存放用户凭证。 用户登录系统之后,会返回一个加密的cookie,当用户访问子应用的时候会带上这个cookie,授权以解密cookie并进行校验,校验通过后即可登录当前用户。
Session方案
我们在单机服务(不涉及到分布式服务的时候,可以很好的使用seesion,可以在过滤器处加上判断,如果此时seesion中已经存在用户,则跳过认证)
Token方案
可参考实现原理
实现单点登录
我们使用Security OAuth2.0 JWT 实现单点登录
首先我们需要了解一些基础知识
JWT
什么是JWT
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
结构
- Header
- Payload
- Signature
代码
public void contextLoads() {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND,90); //设置过期时间
//生成令牌
String token = JWT.create()
.withClaim("username", "测试")//设置自定义用户名
.withClaim("userid", 1)//设置自定义id
.withExpiresAt(instance.getTime())//设置过期时间
.sign(Algorithm.HMAC256("token!Q2W#E$RW"));//设置签名 保密 复杂
//输出令牌
System.out.println(token);
}
@Test
public void getToken(){
//创建验证对象
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("token!Q2W#E$RW")).build();
DecodedJWT decodedJWT = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2OTIyNDA3OTcsInVzZXJpZCI6MSwidXNlcm5hbWUiOiLlsI_lj7YifQ.omSul3kKi9BL5LTXf142usxv4zE1G1DWLZlIqZJGdMo");
System.out.println("用户名:"+decodedJWT.getClaim("username").asString());
System.out.println("用户Id:"+decodedJWT.getClaim("userid").asInt());
System.out.println("过期时间:"+decodedJWT.getExpiresAt());
}
OAuth2.0
OAuth 2.0 是一个开放标准的授权协议,用于通过代表用户进行授权的令牌来保护资源的访问。它提供了一种安全、灵活和易于使用的机制,用于授权第三方客户端访问用户资源,而无需共享用户凭据。
OAuth2.0中的四个角色
-
资源所有者(用户):资源所有者是指拥有受保护资源的用户。这可以是一个终端用户,例如应用程序的最终用户或网站用户。
-
客户端应用程序:客户端应用程序是请求访问资源的第三方应用程序。这可以是一个网站、移动应用程序、桌面应用程序等。客户端应用程序必须先经过授权才能访问资源。
-
授权服务器:授权服务器是负责验证资源所有者身份并颁发访问令牌给客户端应用程序的服务器。客户端应用程序通过与授权服务器进行交互来获取访问令牌。授权服务器还负责验证和处理客户端应用程序的身份验证请求,并确定是否授权其访问受保护的资源。
-
资源服务器:资源服务器是持有受保护资源的服务器。资源服务器负责验证传递给它的访问令牌,并根据令牌中包含的权限信息来提供相应的资源服务。资源服务器在接收到请求时,会检查请求中的访问令牌以确保客户端有访问资源的权限。
OAuth2.0的授权方式
授权码模式(authorization code)
授权码模式是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与服务提供者的认证服务器交互,获取到授权码,再由授权码去交换 access_token。
- 用户访问客户端,客户端将用户导向服务提供商的认证地址。
- 用户选择是否授权客户端访问自己的数据。
- 用户选择授权,将授权码交到客户端。
- 客户端向服务提供商请求令牌,请求中携带授权码。
- 服务提供商向客户端响应令牌。
隐藏模式(implicit)
纯前端代码
https://wx.com/oauth/authorize?
response_type=token&
client_id=CLIENT_ID&
redirect_uri=http://juejin.im/callback&
scope=read
密码模式(resource owner password credentials)
密码模式比较好理解,用户在京东直接输入自己的WX用户名和密码,京东拿着信息直接去WX申请令牌,请求响应的 JSON结果中返回 token。grant_type 为 password 表示密码式授权。
https://wx.com/token?
grant_type=password&
username=USERNAME&
password=PASSWORD&
client_id=CLIENT_ID
凭证式模式(client credentials)
客户端模式比较简单,客户端直接向授权服务器申请令牌,请求响应的 JSON结果中返回 token。grant_type 为 client_credentials 表示客户端模式授权。
客户端模式适用于没有前台页面的后端服务,比如微信小程序、公众号、API 接口等。
客户端模式不需要用户登录,只需要提供客户端 ID 和客户端密钥即可。
https://wx.com/token?
grant_type=client_credentials&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET