Spring Cloud OAuth2分布式权限校验,如何实现疑问?
摘要:分布式权限校验 现在有一个登录问题,假如需要用户登录之后才能查询图书和借阅图书。那要怎么设计? 单体应用的权限校验原理: 浏览器向服务端发送请求,访问网站 服务端接收请求后,创建一个sessionid,存储在服务端,然后发送给浏览器作为Co
分布式权限校验
现在有一个登录问题,假如需要用户登录之后才能查询图书和借阅图书。那要怎么设计?
单体应用的权限校验原理:
浏览器向服务端发送请求,访问网站
服务端接收请求后,创建一个sessionid,存储在服务端,然后发送给浏览器作为Cookie保存
以后浏览器每次请求都携带这个cookie。这样服务端根据cookie中的sessionid判断是哪个用户。
但是分布式系统,各个微服务独立部署,用户登录了用户服务后,借阅服务和图书服务会知道用户登录了吗?
用户登录后,session中的用户数据保存在用户服务中,其他服务没有对应信息,按怎么能让其他服务获取这些信息呢,实现服务间的session同步呢?
将session移出服务器,统一存放!比如存到redis或者MySQL,这样就能保证所有服务获得session。
具体的实现步骤如下:
为每个服务引入依赖:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
修改每个服务配置文件:
spring:
session:
# 存储类型修改为redis
store-type: redis
redis:
# redis 服务器信息
host: localhost
这样设置之后,每个服务只有在登录成功后才能访问!
只要在一个服务登录成功,其他服务就会直接调用,不用重复登录!
注意,如果是服务A 调用服务B,用户在服务B登录,然后访问服务A。那么访问是失败的!
因为服务A没有验证,请求没有携带有效cookie,验证失败,导致其无法访问服务B。
OAuth 2.0 实现单点登录
上面虽然解决了session共享问题,但是由于每个服务都有自己的验证模块,导致整个系统存在冗余功能,那么能否实现只有一个服务进行登录,然后可以访问其他的服务呢?
单点登录正好解决这一问题!
一些常见的第三方登录就是使用这种方式:比如淘宝和咸鱼可以使用支付宝账号登录,虽然他们属于三个不同的应用系统,需要获取支付宝用户信息并授权给其他应用。就要使用OAuth 2.0实现第三方授权。那么到底是怎么实现的呢?
OAuth 2.0一共有四种授权模式:
客户端模式:最简单的一种模式。
先向验证服务器请求获取一个token(令牌)
拿到令牌后去访问对应的资源(比如借阅信息,这样资源服务器才能知道访问者是谁以及是否登录成功)
这里的客户端可以是web、App、小程序或者第三方服务
这种模式比较简单,但是失去了用户验证的意义,压根就不是给用户校验准备的,更适合服务内部调用的场景!
密码模式:相比客户端模式,多了用户名和密码信息,用户需要提供用户名和密码才能获取到token
这种模式有一个缺点:会直接将账号密码信息泄露给客户端(或者第三方应用),这样风险很大,一般不会使用这种模式!
隐式授权模式:用户访问服务时,会重定向到认证服务器,认证服务器返回用户一个认证页面,等待用户授权,用户填写信息完成授权后,认证服务器返回token。用户再携带token去访问服务。
这种模式适合没有服务端的第三方应用页面,验证都是在验证服务器进行,不会泄露敏感信息,但是依然存在泄露token的风险!
授权码模式:最安全的一种模式,也是推荐使用的模式,手机上很多APP都是使用这种模式!
这种模式不会直接返回token,而是返回授权码,真正的token时通过应用服务器访问验证服务器获取的。
