前言
选择 Mysql 5.7 数据库,数据库表分为 服务端表 5 张、客户端表 1 张,具体表如下:
- server
- oauth_client_details:客户端信息
- oauth_access_token:访问令牌
- oauth_refresh_token:访问令牌
- oauth_code:授权码
- oauth_approvals:授权记录
- client
- oauth_client_token:token数据
Server
- oauth_client_details
字段名 | 字段说明 |
---|---|
client_id | 主键,必须唯一,不能为空。 用于唯一标识每一个客户端(client),在注册时必须填写(也可由服务端自动生成)。 对于不同的 grant_type,该字段都是必须的。 在实际应用中的另一个名称叫 appKey,与 client_id 是同一个概念。 |
resource_ids | 客户端所能访问的资源 id 集合,多个资源时用逗号(,)分隔,如: "unity-resource,mobile-resource"。 该字段的值必须来源于与 security.xml 中标签 <oauth2:resource-server> 的属性 resource-id 值一致。 在 security.xml 配置有几个 <oauth2:resource-server> 标签,则该字段可以使用几个该值。在实际应用中, 我们一般将资源进行分类,并分别配置对应的 <oauth2:resource-server> ,如订单资源配置一个 <oauth2:resource-server> , 用户资源又配置一个 <oauth2:resource-server> 。 当注册客户端时,根据实际需要可选择资源 id ,也可根据不同的注册流程,赋予对应的资源 id 。 |
client_secret | 用于指定客户端(client)的访问密匙, 在注册时必须填写(也可由服务端自动生成)。 对于不同的 grant_type ,该字段都是必须的。 在实际应用中的另一个名称叫 appSecret,与 client_secret 是同一个概念。 |
scope | 指定客户端申请的权限范围,可选值包括read,write,trust;若有多个权限范围用逗号(,)分隔,如: "read,write"。 scope 的值与 security.xml 中配置的 ‹intercept-url 的 access 属性有关系。 如 ‹intercept-url 的配置为: <intercept-url pattern="/m/**" access="ROLE_MOBILE,SCOPE_READ"/> 则说明访问该 URL 时的客户端必须有 read 权限范围。write 的配置值为 SCOPE_WRITE,trust 的配置值为 SCOPE_TRUST。 在实际应该中,该值一般由服务端指定,常用的值为 read,write。 |
authorized_grant_types | 指定客户端支持的 grant_type ,可选值包括 authorization_code,password,refresh_token,implicit,client_credentials, 若支持多个 grant_type 用逗号(,)分隔,如: "authorization_code,password"。 在实际应用中,当注册时,该字段是一般由服务器端指定的,而不是由申请者去选择的,最常用的 grant_type 组合有: "authorization_code,refresh_token"(针对通过浏览器访问的客户端); "password,refresh_token"(针对移动设备的客户端)。 implicit 与 client_credentials 在实际中很少使用。 |
web_server_redirect_uri | 客户端的重定向URI,可为空, 当 grant_type 为 authorization_code 或 implicit 时, 在 Oauth 的流程中会使用并检查与注册时填写的 redirect_uri 是否一致。 下面分别说明:(1)当 grant_type= authorization_code 时,第一步 从 spring-oauth-server 获取 'code' 时客户端发起请求时必须有 redirect_uri 参数,该参数的值必须与 web_server_redirect_uri 的值一致。第二步 用 'code' 换取 'access_token' 时客户也必须传递相同的 redirect_uri。在实际应用中,web_server_redirect_uri 在注册时是必须填写的, 一般用来处理服务器返回的 code,验证 state 是否合法与通过 code 去换取 access_token 值。 在 spring-oauth-client 项目中, 可具体参考 AuthorizationCodeController.java 中的 authorizationCodeCallback 方法。(2)当grant_type= implicit 时通过redirect_uri的hash值来传递 access_token 值。如:http://localhost:8080/spring-oauth-client/implicit#access_token=dc891f4a-ac88-4ba6-8224-a2497e013865&token_type=bearer&expires_in=43199 ,然后客户端通过 JS 等从 hash 值中取到 access_token 值。 |
authorities | 指定客户端所拥有的 Spring Security 的权限值(可选), 若有多个权限值,用逗号(,)分隔,如:"ROLE_UNITY,ROLE_USER"。 对于是否要设置该字段的值,要根据不同的 grant_type 来判断, 若客户端在Oauth流程中需要用户的用户名(username)与密码(password)的( authorization_code ,password ), 则该字段可以不需要设置值,因为服务端将根据用户在服务端所拥有的权限来判断是否有权限访问对应的API。 但如果客户端在 Oauth 流程中不需要用户信息的( implicit ,client_credentials ), 则该字段必须要设置对应的权限值, 因为服务端将根据该字段值的权限来判断是否有权限访问对应的API。 |
access_token_validity | 设定客户端的 access_token 的有效时间值(单位:秒),可选,若不设定值则使用默认的有效时间值(60 60 12, 12小时)。 在服务端获取的 access_token JSON 数据中的 expires_in 字段的值即为当前 access_token 的有效时间值。在项目中,可具体参考 DefaultTokenServices.java 中属性 accessTokenValiditySeconds 。在实际应用中,该值一般是由服务端处理的,不需要客户端自定义。 |
refresh_token_validity | 设定客户端的 refresh_token 的有效时间值(单位:秒),可选,若不设定值则使用默认的有效时间值(60 60 24 * 30,30天)。 若客户端的 grant_type 不包括 refresh_token,则不用关心该字段。在项目中,可具体参考 DefaultTokenServices.java 中属性 refreshTokenValiditySeconds 。在实际应用中,该值一般是由服务端处理的,不需要客户端自定义。 |
additional_information | 这是一个预留的字段,在 Oauth 的流程中没有实际的使用,可选,但若设置值,必须是 JSON 格式的数据,如:{"country":"CN","country_code":"086"} 按照 spring-security-oauth 项目中对该字段的描述:Additional information for this client, not need by the vanilla OAuth protocol but might be useful, for example,for storing descriptive information. 在实际应用中, 可以用该字段来存储关于客户端的一些其他信息,如客户端的国家、地区、注册时的IP地址等等。 |
create_time | 数据的创建时间,精确到秒,由数据库在插入数据时取当前系统时间自动生成(扩展字段) |
archived | 用于标识客户端是否已存档(即实现逻辑删除),默认值为'0'(即未存档). 对该字段的具体使用请参考 CustomJdbcClientDetailsService.java ,在该类中,扩展了在查询 client_details 的 SQL 加上 archived = 0 条件 (扩展字段) |
trusted | 设置客户端是否为受信任的,默认为'0'(即不受信任的,1为受信任的)。 该字段只适用于 grant_type="authorization_code" 的情况,当用户登录成功后,若该值为0,则会跳转到让用户 Approve 的页面让用户同意授权,若该字段为 1,则在登录后不需要再让用户 Approve 同意授权(因为是受信任的)。 对该字段的具体使用请参考 OauthUserApprovalHandler.java 。(扩展字段) |
autoapprove | 设置用户是否自动 Approval 操作,默认值为 'false', 可选值包括 'true'、'false'、'read'、'write'。 该字段只适用于 grant_type="authorization_code" 的情况,当用户登录成功后,若该值为 'true' 或支持的 scope 值,则会跳过用户 Approve 的页面,直接授权。 该字段与 trusted 有类似的功能,是 spring-security-oauth2 的 2.0 版本后添加的新属性。 |
- oauth_access_token
字段名 | 字段说明 |
---|---|
create_time | 数据的创建时间,精确到秒,由数据库在插入数据时取当前系统时间自动生成(扩展字段)。 |
token_id | 该字段的值是将 access_token 的值通过 MD5 加密后存储的。 |
token | 存储将 OAuth2AccessToken.java 对象序列化后的二进制数据,是真实的 AccessToken 的数据值。 |
authentication_id | 该字段具有唯一性,是根据当前的 username(如果有),client_id 与 scope 通过 MD5 加密生成的。 |
user_name | 登录时的用户名, 若客户端没有用户名(如grant_type="client_credentials"),则该值等于 client_id。 |
client_id | 客户端 Id。 |
authentication | 存储将 OAuth2Authentication.java 对象序列化后的二进制数据。 |
refresh_token | 该字段的值是将 refresh_token 的值通过 MD5 加密后存储的。 |
- oauth_refresh_token
字段名 | 字段说明 |
---|---|
create_time | 数据的创建时间,精确到秒,由数据库在插入数据时取当前系统时间自动生成(扩展字段)。 |
token_id | 该字段的值是将 refresh_token 的值通过MD5加密后存储的。 |
token | 存储将 OAuth2RefreshToken.java 对象序列化后的二进制数据。 |
authentication | 存储将 OAuth2Authentication.java 对象序列化后的二进制数据。 |
- oauth_code
字段名 | 字段说明 |
---|---|
create_time | 数据的创建时间,精确到秒,由数据库在插入数据时取当前系统时间自动生成(扩展字段)。 |
code | 存储服务端系统生成的 code 的值(未加密)。 |
authentication | 存储将 AuthorizationRequestHolder.java 对象序列化后的二进制数据。 |
Client
- oauth_client_token
该表用于在客户端系统中存储从服务端获取的 token 数据。
字段名 | 字段说明 |
---|---|
create_time | 数据的创建时间,精确到秒,由数据库在插入数据时取当前系统时间自动生成(扩展字段)。 |
token_id | 从服务器端获取到的 access_token 的值。 |
token | 这是一个二进制的字段,存储的数据是 OAuth2AccessToken.java 对象序列化后的二进制数据。 |
authentication_id | 该字段具有唯一性,是根据当前的 username(如果有),client_id 与 scope 通过 MD5 加密生成的。 |
user_name | 登录时的用户名。 |
client_id | 客户端 Id。 |
SQL语句
-- oauth_client_details table
CREATE TABLE `oauth_client_details` (
`client_id` varchar(128) NOT NULL COMMENT '客户端ID',
`resource_ids` varchar(128) DEFAULT NULL COMMENT '资源ID集合,多个资源时用逗号(,)分隔',
`client_secret` varchar(128) DEFAULT NULL COMMENT '客户端密匙',
`scope` varchar(128) DEFAULT NULL COMMENT '客户端申请的权限范围',
`authorized_grant_types` varchar(128) DEFAULT NULL COMMENT '客户端支持的grant_type',
`web_server_redirect_uri` varchar(128) DEFAULT NULL COMMENT '重定向URI',
`authorities` varchar(128) DEFAULT NULL COMMENT '客户端所拥有的Spring Security的权限值,多个用逗号(,)分隔',
`access_token_validity` int(11) DEFAULT NULL COMMENT '访问令牌有效时间值(单位:秒)',
`refresh_token_validity` int(11) DEFAULT NULL COMMENT '更新令牌有效时间值(单位:秒)',
`additional_information` varchar(4096) DEFAULT NULL COMMENT '预留字段',
`autoapprove` varchar(128) DEFAULT NULL COMMENT '用户是否自动Approval操作',
PRIMARY KEY (`client_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='客户端信息';
-- oauth_access_token table
CREATE TABLE `oauth_access_token` (
`token_id` VARCHAR(256) COMMENT 'MD5加密的access_token的值',
`token` BLOB COMMENT 'OAuth2AccessToken.java对象序列化后的二进制数据',
`authentication_id` VARCHAR(256) PRIMARY KEY COMMENT 'MD5加密过的username,client_id,scope',
`user_name` VARCHAR(256) COMMENT '登录的用户名',
`client_id` VARCHAR(256) COMMENT '客户端ID',
`authentication` BLOB COMMENT 'OAuth2Authentication.java对象序列化后的二进制数据',
`refresh_token` VARCHAR(256) COMMENT 'MD5加密果的refresh_token的值'
);
-- oauth_refresh_token table
CREATE TABLE `oauth_refresh_token` (
`token_id` VARCHAR(256) COMMENT 'MD5加密过的refresh_token的值',
`token` BLOB COMMENT 'OAuth2RefreshToken.java对象序列化后的二进制数据',
`authentication` BLOB COMMENT 'OAuth2Authentication.java对象序列化后的二进制数据'
);
-- oauth_code table
CREATE TABLE `oauth_code` (
`code` VARCHAR(256) COMMENT '授权码(未加密)',
`authentication` BLOB COMMENT 'AuthorizationRequestHolder.java对象序列化后的二进制数据'
);
-- oauth_approvals table
CREATE TABLE `oauth_approvals` (
`userId` VARCHAR(256) COMMENT '登录的用户名',
`clientId` VARCHAR(256) COMMENT '客户端ID',
`scope` VARCHAR(256) COMMENT '申请的权限',
`status` VARCHAR(10) COMMENT '状态(Approve或Deny)',
`expiresAt` DATETIME COMMENT '过期时间',
`lastModifiedAt` DATETIME COMMENT '最终修改时间'
);
-- oauth_client_token table
CREATE TABLE `oauth_client_token` (
`token_id` VARCHAR(256) COMMENT 'MD5加密的access_token值',
`token` BLOB COMMENT 'OAuth2AccessToken.java对象序列化后的二进制数据',
`authentication_id` VARCHAR(256) PRIMARY KEY COMMENT 'MD5加密过的username,client_id,scope',
`user_name` VARCHAR(256) COMMENT '登录的用户名',
`client_id` VARCHAR(256) COMMENT '客户端ID'
);