前言
spring boot OAuth2.0默认自带了四种授权模式,比如密码模式,授权码模式等。但是在实际生产过程中,这四种模式并不容易满足要求,所以就需要自定义一些授权模式
maven依赖包
<!--oauth2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
实现
本文自定义平台ID授权模式,只需要传入平台ID即可完成授权,实现方法如下:
1、创建tokenConfig配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
@Configuration
public class TokenConfig {
/**
* 使用内存存储令牌
* @return
*/
@Bean
public TokenStore tokenStore(){
return new InMemoryTokenStore();
}
}
2、配置自定义授权模式类
import com.bw.dsm.config.Oauth2.Platfrom.PlatformGranter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter;
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.*;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Configuration
public class TokenGranterConfig {
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private TokenStore tokenStore;
@Autowired(required = false)
private List<TokenEnhancer> tokenEnhancer;
@Autowired
private RandomValueAuthorizationCodeServices authorizationCodeServices;
private boolean reuseRefreshToken = true;
private AuthorizationServerTokenServices tokenServices;
private TokenGranter tokenGranter;
/**
* 授权模式
*/
@Bean
public TokenGranter tokenGranter() {
if (tokenGranter == null) {
tokenGranter = new TokenGranter() {
private CompositeTokenGranter delegate;
@Override
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
if (delegate == null) {
delegate = new CompositeTokenGranter(getAllTokenGranters());
}
return delegate.grant(grantType, tokenRequest);
}
};
}
return tokenGranter;
}
/**
* 所有授权模式:默认的5种模式 + 自定义的模式
*/
private List<TokenGranter> getAllTokenGranters() {
AuthorizationServerTokenServices tokenServices = tokenServices();
AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices();
OAuth2RequestFactory requestFactory = requestFactory();
//获取默认的授权模式
List<TokenGranter> tokenGranters = getDefaultTokenGranters(tokenServices, authorizationCodeServices, requestFactory);
if (authenticationManager != null) {
// 添加platform模式
tokenGranters.add(new PlatformGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory));
}
return tokenGranters;
}
/**
* 默认的授权模式
*/
private List<TokenGranter> getDefaultTokenGranters(AuthorizationServerTokenServices tokenServices
, AuthorizationCodeServices authorizationCodeServices, OAuth2RequestFactory requestFactory) {
List<TokenGranter> tokenGranters = new ArrayList<>();
// 添加授权码模式
tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetailsService, requestFactory));
// 添加刷新令牌的模式
tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetailsService, requestFactory));
// 添加隐士授权模式
tokenGranters.add(new ImplicitTokenGranter(tokenServices, clientDetailsService, requestFactory));
// 添加客户端模式
tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, requestFactory));
if (authenticationManager != null) {
// 添加密码模式
tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory));
}
return tokenGranters;
}
private AuthorizationServerTokenServices tokenServices() {
if (tokenServices != null) {
return tokenServices;
}
this.tokenServices = createDefaultTokenServices();
return tokenServices;
}
private AuthorizationCodeServices authorizationCodeServices() {
if (authorizationCodeServices == null) {
authorizationCodeServices = new InMemoryAuthorizationCodeServices();
}
return authorizationCodeServices;
}
private OAuth2RequestFactory requestFactory() {
return new DefaultOAuth2RequestFactory(clientDetailsService);
}
private DefaultTokenServices createDefaultTokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore);
tokenServices.setSupportRefreshToken(true);
tokenServices.setReuseRefreshToken(reuseRefreshToken);
tokenServices.setClientDetailsService(clientDetailsService);
tokenServices.setTokenEnhancer(tokenEnhancer());
addUserDetailsService(tokenServices, this.userDetailsService);
return tokenServices;
}
private TokenEnhancer tokenEnhancer() {
if (tokenEnhancer != null) {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(tokenEnhancer);
return tokenEnhancerChain;
}
return null;
}
private void addUserDetailsService(DefaultTokenServices tokenServices, UserDetailsService userDetailsService) {
if (userDetailsService != null) {
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>(userDetailsService));
tokenServices.setAuthenticationManager(new ProviderManager(Collections.singletonList(provider)));
}
}
}
3、创建资源认证配置类,继承AuthorizationServerConfigurerAdapter类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.TokenGranter;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import javax.sql.DataSource;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore;
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private AuthorizationCodeServices authorizationCodeServices;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private TokenGranter tokenGranter;
@Autowired
private PasswordEncoder passwordEncider;
/**
* 令牌管理服务
* @return
*/
@Bean
public AuthorizationServerTokenServices tokenService(){
DefaultTokenServices services = new DefaultTokenServices();
services.setClientDetailsService(clientDetailsService); // 客户端信息服务
services.setSupportRefreshToken(true); // 是否产生刷新令牌
services.setTokenStore(tokenStore); // 令牌存储策略
services.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2个小时
services.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
return services;
}
/**
* 设置授权码模式的授权码如何存取,存储数据库
* @param dataSource
* @return
*/
@Bean
public AuthorizationCodeServices authorizationCodeServices(DataSource dataSource){
return new JdbcAuthorizationCodeServices(dataSource);
}
/**
* 将客户端信息存储到数据库
* @param dataSource
* @return
*/
@Bean
public ClientDetailsService clientDetailsService(DataSource dataSource){
ClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
((JdbcClientDetailsService)clientDetailsService).setPasswordEncoder(passwordEncider);
return clientDetailsService;
}
/**
* 配置客户端详细信息服务
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
}
/**
* 令牌访问端点的安全策略
* @param security
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
.tokenKeyAccess("permitAll()") // oauth/token_key 公开
.checkTokenAccess("permitAll()") // oauth/check_token 公开
.allowFormAuthenticationForClients() // 表单认证,申请令牌
;
}
/**
* 令牌访问端点
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenGranter(tokenGranter) // 配置授权模式 默认的5种模式 + 自定义的模式
.authenticationManager(authenticationManager) // 密码模式需要 认证管理器
.authorizationCodeServices(authorizationCodeServices) // 授权码模式需要 授权码服务
.tokenServices(tokenService()) // 令牌管理服务
.allowedTokenEndpointRequestMethods(HttpMethod.POST) // 允许POST提交
;
}
}
4、配置资源服务器类,继承ResourceServerConfigurerAdapter类
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
/**
* 配置那些url要做oauth验证
* @param http
* @throws Exception
*/
@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/interaction/v1/**").and().authorizeRequests().antMatchers("/interaction/v1/**").authenticated();
// 禁用 session
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().anyRequest().authenticated().and()
.cors().and()
.csrf().disable();
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
// 配置资源 ID
// 配置资源 ID,需要在 oauth_client_details 表中添加,详细查看数据库脚本
resources.resourceId("resourcesId").stateless(true);
// 自定义token失效/错误返回信息
// OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
// authenticationEntryPoint.setExceptionTranslator(new CustomExceptionTranslator());
// resources.authenticationEntryPoint(authenticationEntryPoint);
}
}
5、配置安全认证类,继承WebSecurityConfigurerAdapter类
import com.bw.dsm.config.Oauth2.Platfrom.PlatformAuthenticationProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
//密码编码器
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// 认证管理器
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 自定义platform验证
* 自定义验证方法需要在这里添加到 authenticationProvider 中
* 添加默认的验证方法
* @return
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(platformAuthenticationProvider())
.authenticationProvider(daoAuthenticationProvider())
;
}
/**
* 自定义platform验证
* @return
*/
@Bean
public PlatformAuthenticationProvider platformAuthenticationProvider(){
return new PlatformAuthenticationProvider();
}
/**
* 配置默认的密码授权模式的ProviderManager,否则 密码授权 client认证将不会通过。
* @return
*/
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider(){
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
return daoAuthenticationProvider;
}
//安全拦截机制
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.requestMatchers().antMatchers("/oauth/**")
.and()
.authorizeRequests()
.antMatchers("/oauth/**").authenticated();
}
}
6、创建自定义grant_type模式的实现类,继承AbstractTokenGranter类
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import java.util.LinkedHashMap;
import java.util.Map;
public class PlatformGranter extends AbstractTokenGranter {
// 创建自定义grant_type的名称
private static final String GRANT_TYPE = "platform";
private final AuthenticationManager authenticationManager;
public PlatformGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices
, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) {
super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
this.authenticationManager = authenticationManager;
}
@Override
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
String platformId = parameters.get("platformId");
Authentication userAuth = new PlatformAuthenticationToken(platformId);
((AbstractAuthenticationToken) userAuth).setDetails(parameters);
userAuth = authenticationManager.authenticate(userAuth);
if (userAuth == null || !userAuth.isAuthenticated()) {
throw new InvalidGrantException("Could not authenticate platformId: " + platformId);
}
OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
return new OAuth2Authentication(storedOAuth2Request, userAuth);
}
}
7、新增一个 AuthenticationToken 实现类 PlatformAuthenticationToken,用于存放该授权所需的信息
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
import java.util.Collection;
public class PlatformAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
// ~ Instance fields
// ================================================================================================
private final Object principal;
// ~ Constructors
// ===================================================================================================
/**
* This constructor can be safely used by any code that wishes to create a
* <code>UsernamePasswordAuthenticationToken</code>, as the {@link #isAuthenticated()}
* will return <code>false</code>.
*
*/
public PlatformAuthenticationToken(String openId) {
super(null);
this.principal = openId;
setAuthenticated(false);
}
/**
* This constructor should only be used by <code>AuthenticationManager</code> or
* <code>AuthenticationProvider</code> implementations that are satisfied with
* producing a trusted (i.e. {@link #isAuthenticated()} = <code>true</code>)
* authentication token.
*
* @param principal
* @param authorities
*/
public PlatformAuthenticationToken(Object principal,
Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
super.setAuthenticated(true);
}
// ~ Methods
// ========================================================================================================
@Override
public Object getCredentials() {
return null;
}
@Override
public Object getPrincipal() {
return this.principal;
}
@Override
public void setAuthenticated(boolean isAuthenticated) {
if (isAuthenticated) {
throw new IllegalArgumentException(
"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
}
super.setAuthenticated(false);
}
@Override
public void eraseCredentials() {
super.eraseCredentials();
}
}
8、新增一个 AuthenticationProvider 实现类 PlatformAuthenticationProvider实现授权的逻辑
import com.bw.dsm.service.impl.SpringDataUserDetailsService;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
@Setter
public class PlatformAuthenticationProvider implements AuthenticationProvider {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private SpringDataUserDetailsService springDataUserDetailsService;
@Override
public Authentication authenticate(Authentication authentication) {
PlatformAuthenticationToken authenticationToken = (PlatformAuthenticationToken) authentication;
String platformId = (String) authenticationToken.getPrincipal();
// 调用自定义的通过platformId获取用户信息方法
UserDetails user = springDataUserDetailsService.loadUserByPlatformId(platformId);
if (null == user) {
throw new InternalAuthenticationServiceException("platformId错误");
}
PlatformAuthenticationToken authenticationResult = new PlatformAuthenticationToken(user, user.getAuthorities());
authenticationResult.setDetails(authenticationToken.getDetails());
return authenticationResult;
}
@Override
public boolean supports(Class<?> authentication) {
return PlatformAuthenticationToken.class.isAssignableFrom(authentication);
}
public UserDetailsService getUserDetailsService() {
return userDetailsService;
}
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
}
9、自定义service实现类,从数据库验证平台ID
这里暂未做数据库处理。
import com.alibaba.fastjson.JSON;
import com.bw.dsm.entity.config.OauthSysUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class SpringDataUserDetailsService implements UserDetailsService {
//根据 账号查询用户信息
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//将来连接数据库根据账号查询用户信息
OauthSysUser sysUser = new OauthSysUser();
sysUser.setUsername("sed");
sysUser.setPassword("sed123");;
if(sysUser == null){
//如果用户查不到,返回null,由provider来抛出异常
return null;
}
// TODO: 角色、权限集合
List<GrantedAuthority> grantedAuthorities = new ArrayList();
grantedAuthorities.add(new SimpleGrantedAuthority("USER"));
//将userDto转成json
String principal = JSON.toJSONString(sysUser);
UserDetails userDetails = User.withUsername(principal).password(sysUser.getPassword()).authorities(grantedAuthorities).build();
return userDetails;
}
public UserDetails loadUserByPlatformId(String platformId) throws UsernameNotFoundException {
// 将来连接数据库根据账号查询用户信息
OauthSysUser sysUser = new OauthSysUser();
sysUser.setUsername("sed");
sysUser.setPassword("sed123");
if(sysUser == null){
//如果用户查不到,返回null,由provider来抛出异常
return null;
}
// TODO: 角色、权限集合
List<GrantedAuthority> grantedAuthorities = new ArrayList();
grantedAuthorities.add(new SimpleGrantedAuthority("USER"));
//将sysUser转成json
String principal = JSON.toJSONString(sysUser);
UserDetails userDetails = User.withUsername(principal).password(sysUser.getPassword()).authorities(grantedAuthorities).build();
return userDetails;
}
}
10、需要在配置文件中加上允许覆盖注册配置
# 当遇到同样名字的时候是否允许覆盖注册
spring.main.allow-bean-definition-overriding= true
11、sql脚本
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for oauth_client_details
-- ----------------------------
DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details` (
`client_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '客户端标\r\n识',
`resource_ids` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '接入资源列表',
`client_secret` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '客户端秘钥',
`scope` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`authorized_grant_types` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`web_server_redirect_uri` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`authorities` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`access_token_validity` int DEFAULT NULL,
`refresh_token_validity` int DEFAULT NULL,
`additional_information` longtext CHARACTER SET utf8 COLLATE utf8_general_ci,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`archived` tinyint DEFAULT NULL,
`trusted` tinyint DEFAULT NULL,
`autoapprove` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`client_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='接入客户端信息';
-- ----------------------------
-- Records of oauth_client_details
-- ----------------------------
INSERT INTO `oauth_client_details` VALUES ('client', 'resourcesId', '$2a$10$q0mE0npS9Cm7gQTR4BkXT.kORLOSpxMf2fFOMkyf9roPb0ddRUS12', 'ROLE_ADMIN,ROLE_USER,ROLE_API', 'client_credentials,password,authorization_code,implicit,refresh_token,platform', 'http://www.baidu.com', null, '7200', '259200', null, '2020-12-19 15:20:06', '0', '0', 'false');
12、测试/oauth/token获取token方法
上图可以看到获取token成功,这里我的返回参数内容格式是自定义加密的,关于自定义返回参数内容格式可见: