前面寫了如何配置OAuth2 和 SpringSeurity 授權中心,但是使用的內存存儲的,以及使用的默認InMemoryTokenStore 普通令牌,這次我們修改爲Jwt令牌,並且使用JDBC存儲客戶端信息。
前一篇文章
OAuth2 和 SpringSecurity完成授權認證中心(一)搭建授權認證
初始化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) NOT NULL,
`resource_ids` varchar(255) DEFAULT NULL,
`client_secret` varchar(255) DEFAULT NULL,
`scope` varchar(255) DEFAULT NULL,
`authorized_grant_types` varchar(255) DEFAULT NULL,
`web_server_redirect_uri` varchar(255) DEFAULT NULL,
`authorities` varchar(255) DEFAULT NULL,
`access_token_validity` int(11) DEFAULT NULL,
`refresh_token_validity` int(11) DEFAULT NULL,
`additional_information` longtext,
`create_time` datetime DEFAULT NULL,
`archived` tinyint(4) DEFAULT NULL,
`trusted` tinyint(4) DEFAULT NULL,
`autoapprove` varchar(255) DEFAULT NULL,
PRIMARY KEY (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of oauth_client_details
-- ----------------------------
INSERT INTO `oauth_client_details` VALUES ('c1', 'res1', '$2a$10$LNl3wbdkZX54Tj/9SlxHiOw.a8Iqg0jBplzJcCIbfJVSIPr8mAGvS', 'ROLE_ADMIN,ROLE_USER,ROLE_API', 'client_credentails,password,authorization_code,implicit,refresh_token', 'http://www.baidu.com', null, '7200', '259200', null, '2019-11-13 14:20:08', '0', '0', 'false');
INSERT INTO `oauth_client_details` VALUES ('c2', 'res2', '$2a$10$NlBC84MVb7F95EXYTXwLneXgCca6/GipyWR5NHm8K0203bSQMLpvm', 'ROLE_API', 'client_credentails,password,authorization_code,implicit,refresh_token', 'http://www.baidu.com', null, '31536000', '259200', null, '2019-11-13 14:21:11', '0', '0', 'false');
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for oauth_code
-- ----------------------------
DROP TABLE IF EXISTS `oauth_code`;
CREATE TABLE `oauth_code` (
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`code` varchar(255) DEFAULT NULL,
`authentication` blob,
KEY `code_index` (`code`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
修改TokenConfig,改變令牌策略
@Configuration
public class TokenConfig {
private static final String SIGNING_KEY = "uaa123";
// 令牌存儲策略
@Bean
public TokenStore tokenStore()
{
// Jwt令牌存儲方案
return new JwtTokenStore(assessTokenConverter());
}
@Bean
public JwtAccessTokenConverter assessTokenConverter()
{
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(SIGNING_KEY);//
return converter;
}
}
修改AuthorizationServer.java 類
添加JwtAccessTokenConverter
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
修改令牌管理服務方法
// 令牌管理服務
public AuthorizationServerTokenServices tokenServices()
{
DefaultTokenServices service = new DefaultTokenServices();
service.setClientDetailsService(clientDetailsService); // 客戶端信息服務
service.setSupportRefreshToken(true); // 是否產生刷新令牌
service.setTokenStore(tokenStore); // 設置令牌存儲策略
// 令牌增強
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter));
service.setTokenEnhancer(tokenEnhancerChain);
service.setAccessTokenValiditySeconds(7200);// 令牌默認有效期 2 小時
service.setRefreshTokenValiditySeconds(259200);
return service;
}
配置 客戶端Jdbc詳細信息
private AuthorizationCodeServices authorizationCodeServices;
@Bean
public AuthorizationCodeServices authorizationCodeServices(DataSource dataSource)
{
return new JdbcAuthorizationCodeServices(dataSource);
}
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Bean
public ClientDetailsService clientDetailsService(DataSource dataSource)
{
JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
clientDetailsService.setPasswordEncoder(passwordEncoder);
return clientDetailsService;
}
配置修改客戶端詳細信息方法
// 配置客戶端詳細信息
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
}
最終AuthorizationServer 類
@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore;
@Autowired
private AuthorizationCodeServices authorizationCodeServices;
@Bean
public AuthorizationCodeServices authorizationCodeServices(DataSource dataSource)
{
return new JdbcAuthorizationCodeServices(dataSource);
}
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Bean
public ClientDetailsService clientDetailsService(DataSource dataSource)
{
JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
clientDetailsService.setPasswordEncoder(passwordEncoder);
return clientDetailsService;
}
// 配置客戶端詳細信息
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
}
// 令牌管理服務
public AuthorizationServerTokenServices tokenServices()
{
DefaultTokenServices service = new DefaultTokenServices();
service.setClientDetailsService(clientDetailsService); // 客戶端信息服務
service.setSupportRefreshToken(true); // 是否產生刷新令牌
service.setTokenStore(tokenStore); // 設置令牌存儲策略
// 令牌增強
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter));
service.setTokenEnhancer(tokenEnhancerChain);
service.setAccessTokenValiditySeconds(7200);// 令牌默認有效期 2 小時
service.setRefreshTokenValiditySeconds(259200);
return service;
}
/**
* 令怕i訪問端點
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
// 密碼管理模式
.authenticationManager(authenticationManager)
// 授權碼模式
.authorizationCodeServices(authorizationCodeServices)
.tokenServices(tokenServices()) // 令牌管理服務
.allowedTokenEndpointRequestMethods(HttpMethod.POST); // 允許post提交
}
/**
* 令牌訪問端點的安全策略
* @param security
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()") // /oauth/token_key 公開
.checkTokenAccess("permitAll()") // /auth/check_token 檢測令牌
.allowFormAuthenticationForClients(); // 允許通過表單認證,申請令牌
}
}
修改order 服務
TokenConfig.java
@Configuration
public class TokenConfig{
private static final String SIGNING_KEY = "uaa123";
// 令牌存儲策略
@Bean
public TokenStore tokenStore()
{
// Jwt令牌存儲方案
return new JwtTokenStore(assessTokenConverter());
}
@Bean
public JwtAccessTokenConverter assessTokenConverter()
{
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(SIGNING_KEY);//
return converter;
}
}
修改ResourceServerConfig.java
文件
將all
修改爲數據庫中scope字段中一個 ROLE_ADMIN
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/**").access("#oauth2.hasScope('ROLE_ADMIN')")
.and().csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
super.configure(http);
}
因爲要使用本地 檢查token 所以 將 tokenServices 註釋掉
最終配置類
ResourceServerConfig
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
public static final String RESOURCE_ID = "res1";
@Autowired
private TokenStore tokenStore;
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/**").access("#oauth2.hasScope('ROLE_ADMIN')")
.and().csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
super.configure(http);
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(RESOURCE_ID) // 資源id
.tokenStore(tokenStore)
.stateless(true);
}
}
依次啓動 UaaJwtServer
和 OrderJwtServer
使用postman 進行測試
通過瀏覽器 地址欄獲取 code 的值
點擊Authorize 獲取 code. 查看數據庫
回調的百度鏈接後帶的code
獲取token。
攜帶token 去訪問有的 資源
一、簡化模式
/uaa/oauth/authorize?client_id=c1&response_type=token&scope=all&redirect_uri=http://www.baidu.com
參數描述和授權碼模式,注意reponse_type=token, 說明是 簡化模式
二、密碼模式
POST
/uaa//oauth/token?client_id=c1&client_secret=secret&grant_type=password&username=zhangsan&password=123
- 資源擁有者將用戶名 密碼發給客戶端
- 客戶端拿着資源擁有者的用戶名,密碼向服務器請求令牌
- 授權服務器將令牌發送給client
參數列表:
- client_id : 客戶端標識
- client_secret: 客戶端密鑰
- grant_tyoe: 授權類型 填寫password 表示 密碼模式
- username: 用戶名
- password: 密碼
三、客戶端模式
POST
/uaa/oath/token?grant_type=client_credentials&client_id=c1&client_secret=secret
- 客戶端向授權服務器發送自己的身份呢信息,並請求令牌
- 確認客戶端身份無誤,將頒發令牌給客戶端
參數列表
- client_id:客戶端標識
- client_secret: 客戶端密鑰
- grant_type: 授權類型, client_credentials 表示客戶端模式