刷新令牌策略
注意:刷新令牌只有在授权码模式和密码模式中才有,对应的指定这两种模式时,在类型上加上refresh_token
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId><version>2.3.12.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework.security.oauth</groupId><artifactId>spring-security-oauth2</artifactId><version>2.3.4.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3.12.RELEASE</version>
</dependency>
@Configuration
public class MyOAuth2Config {/*** 加密方式*/@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
}
/*** 当前需要使用内存方式存储了用户令牌,应当使用UserDetailsService才行,否则会报错*/
@Component
public class MyUserDetailService implements UserDetailsService {@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {return new User("admin", passwordEncoder.encode("123456"),AuthorityUtils.commaSeparatedStringToAuthorityList("admin_role"));}
}
@EnableWebSecurity
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MyUserDetailService myUserDetailService;/*** password密码模式要使用此认证管理器*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}/*** 用户类信息*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(myUserDetailService);}
}
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate PasswordEncoder passwordEncoder;@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate MyUserDetailService myUserDetailService;@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("test-pc").secret(passwordEncoder.encode("123456")).resourceIds("oauth2-server").authorizedGrantTypes("password", "authorization_code", "refresh_token").scopes("all").autoApprove(false).redirectUris("http://www.baidu.com/");}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {//密码模式需要配置认证管理器endpoints.authenticationManager(authenticationManager);//刷新令牌获取新令牌时需要endpoints.userDetailsService(myUserDetailService);}
}
令牌管理策略
- ResourceServerTokenServices接口定义了令牌加载、读取方法
- AuthorizationServerTokenServices接口定义了令牌的创建、获取、刷新方法
- ConsumerTokenServices定义了令牌的撤销方法(删除)
- DefaultTokenServices实现了上述三个接口,它包含了一些令牌业务的实现,如创建令牌、读取令牌、刷新令牌、获取客户端ID。默认的创建一个令牌时,是使用 UUID 随机值进行填充的。除了持久化令牌是委托一个 TokenStore 接口实现以外,这个类几乎帮你做了所有事情
TokenStore接口负责持久化令牌,默认情况下,令牌是通过randomUUID产生的32位随机数来进行填充,从而产生的令牌默认是存储在内存中
- 内存存储采用的是TokenStore接口默认实现类InMemoryTokenStore,开发时方便调试,适用单机版
- RedisTokenStore将令牌存储到Redis非关系型数据库,适用于高并发服务
- JdbcTokenStore基于JDBC将令牌存储到关系型数据库中,可以在不同的服务器间共享令牌
- JWtTokenStore将用户信息存储到令牌中,这样后端就可以不存储,前端拿到令牌后可以直接解析出用户信息。
内存管理令牌
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId><version>2.3.12.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework.security.oauth</groupId><artifactId>spring-security-oauth2</artifactId><version>2.3.4.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3.12.RELEASE</version>
</dependency>
@Configuration
public class MyOAuth2Config {@Beanpublic TokenStore tokenStore(){return new InMemoryTokenStore(); }@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
}
/*** 当前需要使用内存方式存储了用户令牌,应当使用UserDetailsService才行,否则会报错*/
@Component
public class MyUserDetailService implements UserDetailsService {@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {return new User("admin", passwordEncoder.encode("123456"),AuthorityUtils.commaSeparatedStringToAuthorityList("admin_role"));}
}
@EnableWebSecurity
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MyUserDetailService myUserDetailService;/*** password密码模式要使用此认证管理器*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}/*** 用户类信息*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(myUserDetailService);}
}
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate MyUserDetailsService myUserDetailsService;@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate PasswordEncoder passwordEncoder;@Autowiredprivate TokenStore tokenStore;@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("test-pc").secret(passwordEncoder.encode("123456")).resourceIds("oauth2-server").authorizedGrantTypes("authorization_code", "password", "implicit", "client_credentials", "refresh_token").scopes("all").autoApprove(false).redirectUris("http://www.baidu.com");}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(authenticationManager);endpoints.userDetailsService(myUserDetailsService);//令牌管理策略endpoints.tokenServices(tokenService());}@Bean public AuthorizationServerTokenServices tokenService() { DefaultTokenServices service=new DefaultTokenServices();//service.setClientDetailsService();//客户端详情服务service.setSupportRefreshToken(true);//支持刷新令牌service.setTokenStore(tokenStore);//令牌存储策略service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天return service;}
}
Redis管理令牌
<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><version>2.3.12.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework.security.oauth</groupId><artifactId>spring-security-oauth2</artifactId><version>2.3.4.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3.12.RELEASE</version>
</dependency>
@Configuration
public class MyOAuth2Config {@Autowiredprivate RedisConnectionFactory redisConnectionFactory;@Beanpublic TokenStore redisTokenStore(){// redis管理令牌return new RedisTokenStore(redisConnectionFactory);}@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
}
/*** 当前需要使用内存方式存储了用户令牌,应当使用UserDetailsService才行,否则会报错*/
@Component
public class MyUserDetailService implements UserDetailsService {@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {return new User("admin", passwordEncoder.encode("123456"),AuthorityUtils.commaSeparatedStringToAuthorityList("admin_role"));}
}
@EnableWebSecurity
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MyUserDetailService myUserDetailService;/*** password密码模式要使用此认证管理器*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}/*** 用户类信息*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(myUserDetailService);}
}
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate MyUserDetailsService myUserDetailsService;@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate PasswordEncoder passwordEncoder;@Autowiredprivate TokenStore tokenStore;@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("test-pc").secret(passwordEncoder.encode("123456")).resourceIds("oauth2-server").authorizedGrantTypes("authorization_code", "password", "implicit", "client_credentials", "refresh_token").scopes("all").autoApprove(false).redirectUris("http://www.baidu.com");}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(authenticationManager);endpoints.userDetailsService(myUserDetailsService);//令牌管理策略endpoints.tokenStore(tokenStore);}
}
JDBC管理令牌
建表语句
具体SQL语句可以去官网查看
-- used in tests that use HSQL
create table oauth_client_details (client_id VARCHAR(128) PRIMARY KEY,resource_ids VARCHAR(256),client_secret VARCHAR(256),scope VARCHAR(256),authorized_grant_types VARCHAR(256),web_server_redirect_uri VARCHAR(256),authorities VARCHAR(256),access_token_validity INTEGER,refresh_token_validity INTEGER,additional_information VARCHAR(4096),autoapprove VARCHAR(256)
);
INSERT INTO `oauth_client_details` VALUES ('test-pc', 'oauth2-server,oauth2-resource', '$2a$10$Q2Dv45wFHgxQkFRaVNAzeOJorpTH2DwHb975VeHET30QsqwuoQOAe', 'all,Base_API', 'authorization_code,password,implicit,client_credentials,refresh_token', 'http://www.baidu.com/', NULL, 50000, NULL, NULL, 'false');create table oauth_client_token (token_id VARCHAR(256),token BLOB,authentication_id VARCHAR(256) PRIMARY KEY,user_name VARCHAR(256),client_id VARCHAR(256)
);create table oauth_access_token (token_id VARCHAR(256),token BLOB,authentication_id VARCHAR(256) PRIMARY KEY,user_name VARCHAR(256),client_id VARCHAR(256),authentication BLOB,refresh_token VARCHAR(256)
);create table oauth_refresh_token (token_id VARCHAR(256),token BLOB,authentication BLOB
);create table oauth_code (code VARCHAR(256), authentication BLOB
);create table oauth_approvals (userId VARCHAR(256),clientId VARCHAR(256),scope VARCHAR(256),status VARCHAR(10),expiresAt TIMESTAMP,lastModifiedAt TIMESTAMP
);-- customized oauth_client_details table
create table ClientDetails (appId VARCHAR(256) PRIMARY KEY,resourceIds VARCHAR(256),appSecret VARCHAR(256),scope VARCHAR(256),grantTypes VARCHAR(256),redirectUrl VARCHAR(256),authorities VARCHAR(256),access_token_validity INTEGER,refresh_token_validity INTEGER,additionalInformation VARCHAR(4096),autoApproveScopes VARCHAR(256)
);
基本使用
<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.3.4.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3.4</version>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version>
</dependency>
server:port: 8080
spring:application:name: oauth2-serverdatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/oauth2?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8username: rootpassword: 123456type: com.alibaba.druid.pool.DruidDataSource
@Configuration
public class MyOauth2Config {/*** druid数据源*/@Bean@ConfigurationProperties(prefix = "spring.datasource")public DataSource druidDataSource() {return new DruidDataSource();}/*** jdbc管理令牌*/@Beanpublic TokenStore jdbcTokenStore() {return new JdbcTokenStore(druidDataSource());}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthenticationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate MyUserDetailsService myUserDetailsService;@Autowiredprivate TokenStore tokenStore;@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("test-pc").secret(passwordEncoder.encode("123456")).resourceIds("oauth2-server").authorizedGrantTypes("authorization_code", "password", "implicit", "client_credentials", "refresh_token").scopes("all").autoApprove(false).redirectUris("http://www.baidu.com");}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(authenticationManager);endpoints.userDetailsService(myUserDetailsService);//令牌管理策略endpoints.tokenStore(tokenStore);}
}
JWT管理令牌
基本使用
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-jwt</artifactId><version>1.1.1.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId><version>2.3.12.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework.security.oauth</groupId><artifactId>spring-security-oauth2</artifactId><version>2.3.4.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3.12.RELEASE</version>
</dependency>
@Configuration
public class MyOAuth2Config {@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic TokenStore tokenStore() {// JWT令牌存储方式return new JwtTokenStore(jwtAccessTokenConverter());}/*** 帮助JWT编码的令牌值在OAuth身份验证信息之间进行转换* JwtAccessTokenConverter是TokenEnhancer的一个实例*/@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();// JWT签名的秘钥,这里使用的是对称加密,资源服务器使用该秘钥来验证converter.setSigningKey("jwt");return converter;}
}
/*** 当前需要使用内存方式存储了用户令牌,应当使用UserDetailsService才行,否则会报错*/
@Component
public class MyUserDetailService implements UserDetailsService {@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {return new User("admin", passwordEncoder.encode("123456"),AuthorityUtils.commaSeparatedStringToAuthorityList("admin_role"));}
}
@EnableWebSecurity
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MyUserDetailService myUserDetailService;/*** password密码模式要使用此认证管理器*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}/*** 用户类信息*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(myUserDetailService);}
}
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate PasswordEncoder passwordEncoder;@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate MyUserDetailService myUserDetailService;@Autowiredprivate TokenStore tokenStore;@Autowiredprivate JwtAccessTokenConverter jwtAccessTokenConverter;@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("test-pc").secret(passwordEncoder.encode("123456")).resourceIds("oauth2-server").authorizedGrantTypes("password", "authorization_code", "refresh_token").scopes("all").autoApprove(false).redirectUris("http://www.baidu.com/");}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {//密码模式需要配置认证管理器endpoints.authenticationManager(authenticationManager);//刷新令牌获取新令牌时需要endpoints.userDetailsService(myUserDetailService);endpoints.tokenStore(tokenStore);//配置JwtAccessToken转换器,将值转换为jwtendpoints.accessTokenConverter(jwtAccessTokenConverter);}@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {//security.allowFormAuthenticationForClients();//所有人都可访问/oauth/token_key,后面要获取公钥,默认拒绝访问//注意:rsa时才有用,其他需要先认证才访问该接口security.tokenKeyAccess("permitAll()");//认证后可访问/oauth/check_token,默认拒绝访问security.checkTokenAccess("permitAll()");}
}
获取JWT令牌,并将其解析
实现TokenEnhancer自定义token内容增强器
Token解析将得到PAYLOAD,如果想在JWT中添加额外信息,需要实现TokenEnhancer,相当于是一个Token增强器
@Configuration
public class MyOAuth2Config {@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic TokenStore tokenStore() {// JWT令牌存储方式return new JwtTokenStore(jwtAccessTokenConverter());}/*** 帮助JWT编码的令牌值在OAuth身份验证信息之间进行转换* JwtAccessTokenConverter是TokenEnhancer的一个实例*/@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();// JWT签名的秘钥,这里使用的是对称加密,资源服务器使用该秘钥来验证converter.setSigningKey("jwt");return converter;}
}
/*** token内容增强器*/
@Component
public class JwtTokenEnhancer implements TokenEnhancer {@Overridepublic OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {Map<String, Object> info = new HashMap<>();//为原有的token的载荷增加一些内容//在对token进行解密时就可以拿到这里添加的信息info.put("enhance", "enhance info");((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(info);return oAuth2AccessToken;}
}
@EnableWebSecurity
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MyUserDetailService myUserDetailService;/*** password密码模式要使用此认证管理器*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}/*** 用户类信息*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(myUserDetailService);}
}
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate PasswordEncoder passwordEncoder;@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate MyUserDetailService myUserDetailService;@Autowiredprivate TokenStore tokenStore;@Autowiredprivate JwtAccessTokenConverter jwtAccessTokenConverter;@Autowiredprivate JwtTokenEnhancer jwtTokenEnhancer;@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("test-pc").secret(passwordEncoder.encode("123456")).resourceIds("oauth2-server").authorizedGrantTypes("password", "authorization_code", "refresh_token").scopes("all").autoApprove(false).redirectUris("http://www.baidu.com/");}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {//配置JWT的内容增强器,TokenEnhancer可以对token进行增强TokenEnhancerChain enhancerChain = new TokenEnhancerChain();List<TokenEnhancer> delegates = new ArrayList<>();//添加token增强器delegates.add(jwtTokenEnhancer);//添加转换器delegates.add(jwtAccessTokenConverter);//把增强内容放入增强链中enhancerChain.setTokenEnhancers(delegates);//密码模式需要配置认证管理器endpoints.authenticationManager(authenticationManager);//刷新令牌获取新令牌时需要endpoints.userDetailsService(myUserDetailService);endpoints.tokenStore(tokenStore);//配置JwtAccessToken转换器,将值转换为jwtendpoints.accessTokenConverter(jwtAccessTokenConverter);//配置token增强链endpoints.tokenEnhancer(enhancerChain);}@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {//所有人都可访问/oauth/token_key,后面要获取公钥,默认拒绝访问security.tokenKeyAccess("permitAll()");//认证后可访问/oauth/check_token,默认拒绝访问security.checkTokenAccess("permitAll()");}
}
利用令牌管理服务管理JWT令牌
@Configuration
public class MyOAuth2Config {@Autowiredprivate JwtTokenEnhancer jwtTokenEnhancer;@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}@Beanpublic TokenStore tokenStore(){return new JwtTokenStore(jwtAccessTokenConverter());}@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter(){JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setSigningKey("123");return converter;}/*** 令牌管理服务*/@Beanpublic AuthorizationServerTokenServices authorizationServerTokenServices(){DefaultTokenServices tokenServices = new DefaultTokenServices();// 客户端详情,因为是向客户端颁发令牌,所以需要知道是哪一个客户端/*tokenServices.setClientDetailsService();*/// 是否支持刷新令牌tokenServices.setSupportRefreshToken(true);// 令牌存储策略tokenServices.setTokenStore(tokenStore());// 设置令牌增强TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();List<TokenEnhancer> delegates = new ArrayList<>();delegates.add(jwtTokenEnhancer);delegates.add(jwtAccessTokenConverter());tokenEnhancerChain.setTokenEnhancers(delegates);tokenServices.setTokenEnhancer(tokenEnhancerChain);// access_token默认有效期2小时tokenServices.setAccessTokenValiditySeconds(7200);// refresh_token默认有效期3天tokenServices.setRefreshTokenValiditySeconds(259200);return tokenServices;}
}
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate PasswordEncoder passwordEncoder;@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate MyUserDetailService myUserDetailService;@Autowiredprivate AuthorizationServerTokenServices authorizationServerTokenServices;@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("test-pc").secret(passwordEncoder.encode("123456")).resourceIds("oauth2-server").authorizedGrantTypes("password", "authorization_code", "refresh_token").scopes("all").autoApprove(false).redirectUris("http://www.baidu.com/");}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {//密码模式需要配置认证管理器endpoints.authenticationManager(authenticationManager);//刷新令牌获取新令牌时需要endpoints.userDetailsService(myUserDetailService);//令牌管理服务endpoints.tokenServices(authorizationServerTokenServices);}@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {//所有人都可访问/oauth/token_key,后面要获取公钥,默认拒绝访问security.tokenKeyAccess("permitAll()");//认证后可访问/oauth/check_token,默认拒绝访问security.checkTokenAccess("permitAll()");}
}
令牌端点的安全策略
- /oauth/authorize:申请授权码code,涉及类AuthorizationEndpoint
- /oauth/token:获取令牌token,涉及类TokenEndpoint
- /oauth/check_token:用于资源服务器请求端点来检查令牌是否有效,涉及类CheckTokenEndpoint
- /oauth/confirm_access:用于确认授权提交,涉及类WhitwlabelApprovalEndpoint
- /oauth/error:授权错误信息,涉及类WhitelabelErrorEndpoint
- /oauth/token_key:提供公有密钥的端点,使用JWT令牌时会使用,涉及类TokenKeyEndpoint
默认情况下/oauth/check_token和/oauth/token_key端点默认是denyAll()拒绝访问的权限,如果这两个端点需要访问,要对他们进行认证和授权才可以访问
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthenticationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate MyUserDetailsService myUserDetailsService;@Autowiredprivate TokenStore tokenStore;@Autowiredprivate AuthorizationCodeServices jdbcAuthorizationCodeServices;@Autowiredprivate ClientDetailsService jdbcClientDetailsService;@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.withClientDetails(jdbcClientDetailsService);}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(authenticationManager);endpoints.userDetailsService(myUserDetailsService);//令牌管理策略endpoints.tokenStore(tokenStore);//授权码管理策略,针对授权码模式有效,会将授权码放到oauth_code表,授权后就删除它endpoints.authorizationCodeServices(jdbcAuthorizationCodeServices);}@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {//所有人都可访问/oauth/token_key,后面要获取rsa公钥,默认拒绝访问//注意:rsa时才有用,其他需要先认证才访问该接口security.tokenKeyAccess("permitAll()");//认证后可访问/oauth/check_token,默认拒绝访问security.checkTokenAccess("isAuthenticated()");}
}