转载

微服务API开放授权平台的设计与实现

本文所介绍的项目是一个基于oath2协议的应用,实现的的功能逻辑与QQ互联,微博开放平台类似,都是同一套认证授权流程。

项目结构简单易懂,却不偷工减料,在学习完本文内容后,读者可以直接获取文中的项目代码用于学习或者copy到公司的生产项目中修改后使用,真正达到学以致用的目的。

所涉及技术栈:

  • java
  • springboot 2.0.1.RELEASE
  • spring security 2.0.1.RELEASE
  • spring cloud oauth2 2.0.0.M7
  • mybatis 2.0.1

本项目包括功能有

  • 新用户
  1. 用户注册自动分配角色权限
  2. 用户只能访问自己所拥有的角色权限访问路径
  • 开放平台
  1. 用户可以申请获取客户ID和客户密钥
  2. 用户可以通过客户ID获取授权码
  3. 用户可以通过客户ID和密钥以及授权码获取access token 和referrsh token和scope
  • 资源api服务(order-service/open-api-service)
  1. 可自定义配置需授权url
  2. 可自定义配置受限url的访问scope
  3. 未授权用户或访问权限不足用户,页面提示相信息
  4. 用户通过access token 来访问对应url

项目概览

首先来看一下项目的结构图,了解项目的大致布局

微服务API开放授权平台的设计与实现
  • .idea:idea工具生成的文件
  • docker: 存放Dockerfile文件用于构建容器镜像
  • config: 项目中关于spring security和web的配置
  • controller:请求控制器
  • entity: 对象实体类包
  • handler:逻辑处理类包
  • mapper:存放mybatis mapper接口类
  • service: 业务逻辑处理类
  • util: 通用的工具类
  • postman:postman工具的测试用例
  • sql:项目的初始化sql语句
  • templates: 页面模板文件

接下来正式介绍关于项目的细节,由于项目本身就已经有不少中文注释,所以在讲解的时候会收缩起一些代码的具体实现,如果读者不习惯可以在这里点 在线比对阅读 或者fork到自己的项目里阅读==> 项目代码

用户是如何被拦截认证的

微服务API开放授权平台的设计与实现
@EnableWebSecurity
微服务API开放授权平台的设计与实现
  1. 重写 WebSecurityConfigurerAdapter 的 configure(HttpSecurity http) 方法
  2. 指定哪里请求url是不需要拦截直接放行的
  3. 指定哪些请求是需要拦截校验的
微服务API开放授权平台的设计与实现
  1. 重写 WebSecurityConfigurerAdapter 的 configure(AuthenticationManagerBuilder auth) 方法
  2. 指定处理认证的service服务类为 MyUserDetailsService
  3. 比对输入的密码和数据库中的用户密码是否一致
微服务API开放授权平台的设计与实现
  1. 自定类 MyUserDetailsService 实现了 spring security的UserDetailsService 接口
  2. 重写 loadUserByUsername(String username) 方法, 其中username是页面传的属性和值,属性是固定的
  3. 获取用户权限表对应的权限详情,并把内容设置到 UserDetails.Authorities属性中
  4. 返回 UserDetails的子类 User

用户注册自动分配角色权限

用户注册则往用户表插入数据,同时往用户角色表也插入一份数据。

当然也可以设计的更复杂些,比如根据来源、时间、白名单、内部推荐等设置不同的权限,读者可自行扩展。

微服务API开放授权平台的设计与实现

用户只能访问自己所拥有的角色权限访问路径

微服务API开放授权平台的设计与实现
  1. 取出当前用户的所有权限
  2. 取出权限的权限标识字段,并包装成一个List 集合
  3. 保存包装的权限list集合到 UserDetails 对象中
微服务API开放授权平台的设计与实现
  1. 取出所有权限表中内容
  2. http.authorizeRequests()获取当前的认证对象
  3. 把权限表中的内容全部设置到 authorizeRequests中, antMatchers表示拦截的url, hasAnyAuthority表示可以访问的权限标识
  4. 因为在上图中user已经设置了自己所拥有权限的权限标识,所以可以访问被拦截的url
微服务API开放授权平台的设计与实现

用户可以申请获取客户ID和客户密钥

首先来看一下表结构,oauth_client_details 为spring cloud oath2自带的表, user_client_secret 为我们自己创建的表

微服务API开放授权平台的设计与实现
微服务API开放授权平台的设计与实现
微服务API开放授权平台的设计与实现
  1. 生成 OauthClientDetails 数据并保存至数据库中
  2. 获取当前登录人信息,并绑定OauthClientDetails的clientId至user_client_secret表中

用户可以通过客户ID获取授权码

具体的实现在spring-security-oauth包中的, 非本项目内的自我实现

客户ID获取授权码 请求url: http://localhost:8080/oauth/authorize?response_type=code&client_id=client_92&redirect_uri=http://localhost:8080/code

微服务API开放授权平台的设计与实现
微服务API开放授权平台的设计与实现
  1. 因为是要获取授权码,response_type=code为固定值
  2. 客户申请的客户ID
  3. oauth_client_details 表中的 web_server_redirect_uri

用授权码获取access_token

具体的实现在spring-security-oauth包中的 org.springframework.security.oauth2.provider.endpoint.TokenEndpoint 类,有兴趣的同学可以在里面进行debug调试

用授权码获取access_token 请求url: http://localhost:8080/oauth/token?grant_type=authorization_code&code=8fGtOV&client_id=client_92&client_secret=123456&redirect_uri=http://localhost:8080/code&scope=all

微服务API开放授权平台的设计与实现
  1. 通过客户ID获取到的授权码
  2. 客户申请的客户ID
  3. 客户申请的客户ID配套的客户秘钥
  4. oauth_client_details 表中的 web_server_redirect_uri
  5. oauth_client_details 表中的 scope
    微服务API开放授权平台的设计与实现
# 出现如下类似错误标识code失效,重新在获取授权码操作即可
{
    "error": "invalid_grant",
    "error_description": "Invalid authorization code: iq30f9"
}
复制代码
原文  https://juejin.im/post/5da4452c518825647c513ba9
正文到此结束
Loading...