ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
OAuth 2.0 简单介绍 **角色**:先区分下OAuth 2.0 中有哪些角色,注意这里根据自己理解来写的,阮一峰博客里写的更精确: Client: 客户端,也就是Third-party application - 第三方应用程序 Service:服务端,也就是服务的提供者 User: 用户,也就是Resource Owner - 资源所有者 User Agent:用户代理,如浏览器,下文中将其与Client合并考虑。 Authorization Server:认证服务器,即服务提供商专门用来处理认证的服务器。 Resource Server:资源服务器,即服务提供商存放用户生成的资源的服务器。 **模式** 在不需要第三方认证支持时,我们常用的就是简化模式: (A)客户端将用户导向认证服务器。 (B)用户决定是否给于客户端授权。 (C)假设用户给予授权,认证服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令牌。 (D)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。 (E)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。 (F)浏览器执行上一步获得的脚本,提取出令牌。 (G)浏览器将令牌发给客户端。 **Spring Cloud 微服务下** Spring Cloud 下我们这里使用简化模式,主要是登录、授权、Token管理,角色大体如下: User: 也就是用户,用户一般直接与Client交互,REST API后台一般不需要考虑。 Gateway + Resource Server :资源服务器对请求进行认证,一般整合在网关中,这样可以很方便的统一处理所有请求。 Authorization Server: 授权服务器,进行授权和Token管理。 Client: 调用API的应用,一般是前端、移动App或者第三方应用 Token Store: 令牌存储,多个服务如果每次请求都通过授权服务器进行Token查询,效率底下,所以需要统一存储、交互令牌信息,常用Redis Services: 提供正在业务/功能/API的服务。 大概画个图,这里以Client为前端为例,注意不涉及用户和前端的交互: **JWT 简介** JWT -- Json Web Token, 如其名,使用Json方式保存Web Token的协议。网上有各种解读,个人理解,这就是一个 客户端Session - Session保存在客户端,而不是通常的保存在服务端。 构成 JWT三部分组成: Header 头部:JSON方式描述JWT基本信息,如类型和签名算法。使用Base64编码为字符串 Payload 载荷:JSON方式描述JWT信息,除了标准定义的,还可以添加自定义的信息。同样使用Base64编码为字符串。 iss: 签发者 sub: 用户 aud: 接收方 exp(expires): unix时间戳描述的过期时间 iat(issued at): unix时间戳描述的签发时间 Signature 签名:将前两个字符串用 . 连接后,使用头部定义的加密算法,利用密钥进行签名,并将签名信息附在最后。 注意: Payload 使用 Base64编码,所以就是明文的,不要存放任何机密信息。 优缺点 当然带来一些好处: 服务端内存占用少了 不需要维护session状态了,真正无状态 单点登录 so easy,只要后台服务能解读,Cookie 设置为顶级域名 有好处当然就有不太好的: 每个请求就要对JWT进行解密,验证 Token有效期只有超时,没有退出。当然有一些做法,上面也提到了,jwt-authentication-how-to-implement-logout XSS攻击问题,一个讨论: Is it OK to store the JWT in local/session storage 我个人的看法是: 使用JWT,同时在Redis保存信息,在API网关进行详细的验证;各服务则只简单校验Token本身是否篡改。 Spring Cloud OAuth 解读 角色 Spring Cloud OAuth中将角色为三个,这点从源码中包org.springframework.security.oauth2.config.annotation.web.configurers 中包含三个Enable注解就可以看出来: EnableAuthorizationServer -- 使能授权服务器 EnableResourceServer -- 使能资源服务器 EnableOAuth2Client -- 使能客户端,如需要第三方授权来调用,应该使用此注解。 AuthorizationServer 授权服务配置 一. 首先当然需要使能,在配置类或 Application 上类添加注解: @EnableAuthorizationServer,添加该注解后会自动添加OAuth2的多个endpoint, 相关实现代码在包 org.springframework.security.oauth2.provider.endpoint: /oauth/authorize:验证接口, AuthorizationEndpoint /oauth/token:获取token /oauth/confirm_access:用户授权 /oauth/error:认证失败 /oauth/check_token:资源服务器用来校验token /oauth/token_key:jwt模式下获取公钥;位于:TokenKeyEndpoint ,通过 JwtAccessTokenConverter 访问key 二. 配置入口为接口:AuthorizationServerConfigurer, 通过扩展AuthorizationServerConfigurerAdapter 实现来进行配置。 Spring Boot 2中很多 Adapter已经取消,直接利用 Java8 Interface Default特性来实现,不过到我写此文时 security 还没改,当然也许是我没注意到。 三. 简单看一下 AuthorizationServerConfigurer 接口的方法, 一共配置三个属性: AuthorizationServerSecurityConfigurer :声明安全约束,哪些允许访问,哪些不允许访问。配置 AuthorizationServer 的安全属性,也就是endpoint /oauth/token 。/oauth/authorize 则和其它用户 REST 一样保护。可以不配置。 ClientDetailsServiceConfigurer : 配置 ClientDetailsService 独立client客户端的信息。包括权限范围、授权方式、客户端权限等配置。授权方式有4种:implicit, client_redentials, password , authorization_code, 其中密码授权方式必须结合 AuthenticationManager 进行配置。必须至少配置一个客户端。 AuthorizationServerEndpointsConfigurer : 配置AuthorizationServer 端点的非安全属性,也就是 token 存储方式、token 配置、用户授权模式等。默认不需做任何配置,除非使用 密码授权方式, 这时候必须配置 AuthenticationManager。 四. 其中,Token管理: Token 生命周期管理接口 AuthorizationServerTokenServices, 默认使用: DefaultTokenServices。 Token存储通过配置 TokenStore,默认使用内存存储。AuthorizationServerEndpointsConfigurer 或 DefaultTokenServices 入口配置。配置方式有 InMemoryTokenStore 默认方式,保存在本地内存 JdbcTokenStore 存储数据库 RedisTokenStore 存储Redis,这应该是微服务下比较常用方式 JwtTokenStore AccessTokenConverter 五. 加密算法配置 在spring5之后,必须配置加密算法。 测试时候可以用无加密算法,参考:no-passwordencoder-mapped-id-null @SuppressWarnings("deprecation") @Bean public NoOpPasswordEncoder passwordEncoder() { return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); } 配置加密算法,当然也可以配置其它算法: @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } 具体参考: https://www.jianshu.com/p/4089c9cc2dfd