https://gitee.com/DanShenGuiZu/learnDemo/tree/master/auth2.0--learn/simple-auth2.0/oauth_parent
JWT令牌较长,占存储空间比较大。
包含令牌的类型(即JWT)及使用的哈希算法(如HMACSHA256或RSA)
{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "1234567890",
"name": "456",
"admin": true
}
HMACSHA256(
base64UrlEncode(header)+"."+
base64UrlEncode(payload),
secret)
package com.feizhou.oauth.config;
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.bcrypt.BCryptPasswordEncoder;
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.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import java.util.Arrays;
/**
* 描述该类- JPA
*
* @author zhoufei
* @class: AuthorizationServer
* @date 2020/10/28 21:26
* @Verson 1.0 -2020/10/28 21:26
* @see
*/
@Configuration
@EnableAuthorizationServer // 配置授权服务。
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Autowired
private JwtAccessTokenConverter accessTokenConverter;
@Autowired
// 授权码服务
private AuthorizationCodeServices authorizationCodeServices;
@Autowired
// 认证管理
private AuthenticationManager authenticationManager;
@Autowired
// 令牌管理服务
private AuthorizationServerTokenServices authorizationServerTokenServices;
@Autowired
// 令牌存储策略
private TokenStore tokenStore;
@Autowired
// 客户端详情服务,也就是configure(ClientDetailsServiceConfigurer clients)方法
private ClientDetailsService clientDetailsService;
// 用来配置客户端详情服务
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 这里是第三方合作用户的客户id,秘钥的配置
// 使用in-memory存储
clients.inMemory()
// client_id,用户账号
.withClient("c1")
// 客户端密钥
.secret(new BCryptPasswordEncoder().encode("secret"))
// 资源列表,资源标识
.resourceIds("res1")
// 授权类型(4种)
.authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit",
"refresh_token")
// 客戶端允许的授权范围
.scopes("all")
// false跳转到授权页面,让用户点击授权,如果是true,相当于自动点击授权,就不跳转授权页面
.autoApprove(false)//
// 加上验证回调地址,返回授权码信息
.redirectUris("http://www.baidu.com");
// 如果有多个用户,配置多个客户详情
// .and().withClient()
}
// 令牌管理服务
@Bean
public AuthorizationServerTokenServices tokenService() {
DefaultTokenServices service = new DefaultTokenServices();
service.setClientDetailsService(clientDetailsService);
service.setSupportRefreshToken(true);// 支持刷新
service.setTokenStore(tokenStore);// 令牌存储
// 令牌增强
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
service.setTokenEnhancer(tokenEnhancerChain);
service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
return service;
}
@Override
// 用来配置令牌(token)的访问端点
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
// 指定认证管理器
.authenticationManager(authenticationManager)
// 授权码模式需要
.authorizationCodeServices(authorizationCodeServices)
// 令牌管理服务
.tokenServices(authorizationServerTokenServices)
// jwt格式Token
.accessTokenConverter(accessTokenConverter)
// 允许post提交
.allowedTokenEndpointRequestMethods(HttpMethod.POST);
}
@Bean
// 授权码服务器
public AuthorizationCodeServices authorizationCodeServices() {
// 授权码模式的授权码采用内存方式存储
return new InMemoryAuthorizationCodeServices();
}
@Override
// 用来配置令牌端点的安全约束,拦截规则
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
// 提供公有密匙的端点,如果你使用JWT令牌的话, 允许
.tokenKeyAccess("permitAll()")
// oauth/check_token:用于资源服务访问的令牌解析端点,允许
.checkTokenAccess("permitAll()")
// 表单认证,申请令牌
.allowFormAuthenticationForClients();
}
}
package com.feizhou.oauth.config;
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.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
/**
* @author Administrator
* @version 1.0
**/
@Configuration
public class TokenConfig {
// 对称秘钥,资源服务器使用该秘钥来验证
private String SIGNING_KEY = "uaa123";
@Bean
public TokenStore tokenStore() {
// JWT令牌存储方案
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(SIGNING_KEY); // 对称秘钥,资源服务器使用该秘钥来验证
return converter;
}
/* @Bean
public TokenStore tokenStore() {
//使用内存存储令牌(普通令牌)
return new InMemoryTokenStore();
}*/
}
package com.feizhou.oauth.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
/**
* @author Administrator
* @version 1.0
**/
@Configuration
@EnableResourceServer
public class ResouceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
// 令牌存储策略
private TokenStore tokenStore;
// 授权服务的资源列表
public static final String RESOURCE_ID = "res1";
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
// 资源 id
.resourceId(RESOURCE_ID)
// // 令牌服务
// .tokenServices(tokenService())
// 令牌服务
.tokenStore(tokenStore)
.stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/**")
// 所有的访问,授权访问都要是all,和认证服务器的授权范围一一对应
.access("#oauth2.hasScope('all')")
//去掉防跨域攻击
.and().csrf().disable()
//session管理
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
// @Bean
// // 资源服务令牌解析服务
// public ResourceServerTokenServices tokenService() {
// // 使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secret
// RemoteTokenServices service = new RemoteTokenServices();
// service.setCheckTokenEndpointUrl("http://localhost:8081/oauth/check_token");
// service.setClientId("c1");
// service.setClientSecret("secret");
// return service;
// }
}
package com.feizhou.oauth.config;
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.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
/**
* @author Administrator
* @version 1.0
**/
@Configuration
public class TokenConfig {
// 对称秘钥,资源服务器使用该秘钥来验证
private String SIGNING_KEY = "uaa123";
@Bean
public TokenStore tokenStore() {
// JWT令牌存储方案
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(SIGNING_KEY); // 对称秘钥,资源服务器使用该秘钥来验证
return converter;
}
/* @Bean
public TokenStore tokenStore() {
//使用内存存储令牌(普通令牌)
return new InMemoryTokenStore();
}*/
}
package com.feizhou.oauth.config;
import java.util.Arrays;
import javax.sql.DataSource;
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.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.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
/**
* 描述该类- JPA
*
* @author zhoufei
* @class: AuthorizationServer
* @date 2020/10/28 21:26
* @Verson 1.0 -2020/10/28 21:26
* @see
*/
@Configuration
@EnableAuthorizationServer // 配置授权服务。
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Autowired
private JwtAccessTokenConverter accessTokenConverter;
@Autowired
// 授权码服务
private AuthorizationCodeServices authorizationCodeServices;
@Autowired
// 认证管理
private AuthenticationManager authenticationManager;
@Autowired
// 令牌管理服务
private AuthorizationServerTokenServices authorizationServerTokenServices;
@Autowired
// 令牌存储策略
private TokenStore tokenStore;
@Autowired
// 客户端详情服务,也就是configure(ClientDetailsServiceConfigurer clients)方法
private ClientDetailsService clientDetailsService;
@Autowired
// 加密方式
private PasswordEncoder passwordEncoder;
//将客户端信息存储到数据库
@Bean
public ClientDetailsService clientDetailsService(DataSource dataSource) {
ClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
((JdbcClientDetailsService) clientDetailsService).setPasswordEncoder(passwordEncoder);
return clientDetailsService;
}
// 用来配置客户端详情服务
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//数据库配置
clients.withClientDetails(clientDetailsService);
}
// // 用来配置客户端详情服务
// @Override
// public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// // 这里是第三方合作用户的客户id,秘钥的配置
// // 使用in-memory存储
// clients.inMemory()
// // client_id,用户账号
// .withClient("c1")
// // 客户端密钥
// .secret(new BCryptPasswordEncoder().encode("secret"))
// // 资源列表,资源标识
// .resourceIds("res1")
// // 授权类型(4种)
// .authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit",
// "refresh_token")
// // 客戶端允许的授权范围
// .scopes("all")
// // false跳转到授权页面,让用户点击授权,如果是true,相当于自动点击授权,就不跳转授权页面
// .autoApprove(false)//
// // 加上验证回调地址,返回授权码信息
// .redirectUris("http://www.baidu.com");
//
// // 如果有多个用户,配置多个客户详情
// // .and().withClient()
//
// }
// 令牌管理服务
@Bean
public AuthorizationServerTokenServices tokenService() {
DefaultTokenServices service = new DefaultTokenServices();
service.setClientDetailsService(clientDetailsService);
service.setSupportRefreshToken(true);// 支持刷新
service.setTokenStore(tokenStore);// 令牌存储
// 令牌增强
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
service.setTokenEnhancer(tokenEnhancerChain);
service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
return service;
}
@Override
// 用来配置令牌(token)的访问端点
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
// 指定认证管理器
.authenticationManager(authenticationManager)
// 授权码模式需要
.authorizationCodeServices(authorizationCodeServices)
// 令牌管理服务
.tokenServices(authorizationServerTokenServices)
// jwt格式Token
.accessTokenConverter(accessTokenConverter)
// 允许post提交
.allowedTokenEndpointRequestMethods(HttpMethod.POST);
}
// @Bean
// // 授权码服务器
// public AuthorizationCodeServices authorizationCodeServices() {
// // 授权码模式的授权码采用内存方式存储
// return new InMemoryAuthorizationCodeServices();
// }
@Bean
// 授权码服务器
public AuthorizationCodeServices authorizationCodeServices(DataSource dataSource) {
//授权码模式的授权码采用数据库方式存储
return new JdbcAuthorizationCodeServices(dataSource);
}
@Override
// 用来配置令牌端点的安全约束,拦截规则
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
// 提供公有密匙的端点,如果你使用JWT令牌的话, 允许
.tokenKeyAccess("permitAll()")
// oauth/check_token:用于资源服务访问的令牌解析端点,允许
.checkTokenAccess("permitAll()")
// 表单认证,申请令牌
.allowFormAuthenticationForClients();
}
}
spring.application.name=oauth-authorizationServer
server.port=8081
spring.datasource.url = jdbc:mysql://zhoufei.ali.db.com:3306/test?useUnicode=true
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.main.allow-bean-definition-overriding=true
CREATE TABLE oauth_client_details (
client_id varchar(255) NOT NULL COMMENT '客户端标识',
resource_ids varchar(255) DEFAULT NULL COMMENT '接入资源列表',
client_secret varchar(255) DEFAULT NULL COMMENT '客户端秘钥',
scope varchar(255) DEFAULT NULL COMMENT '授权访问',
authorized_grant_types varchar(255) DEFAULT NULL COMMENT '授权类型',
web_server_redirect_uri varchar(255) DEFAULT NULL COMMENT '重定向地址',
authorities varchar(255) DEFAULT NULL COMMENT '客户端秘钥',
access_token_validity int(11) DEFAULT NULL COMMENT 'token过期时间',
refresh_token_validity int(11) DEFAULT NULL COMMENT '刷新 token',
additional_information longtext,
archived tinyint(4) DEFAULT NULL,
trusted tinyint(4) DEFAULT NULL,
autoapprove varchar(255) DEFAULT NULL,
create_time timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (client_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端信息表';
CREATE TABLE oauth_code (
code varchar(255) DEFAULT NULL COMMENT '授权码',
authentication blob,
create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='授权码表';
INSERT INTO test.oauth_client_details (client_id, resource_ids, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, archived, trusted, autoapprove, create_time) VALUES ('c1', 'res1', '$2a$10$dIONDbZ6k.CHLd6eCJZQS.52LkcutcjJI1CgnsLOl9RNzaPNMaRTS', 'all,ROLE_USER,ROLE_API', 'client_credentials,password,authorization_code,implicit,refresh_token', 'http://www.baidu.com', NULL, '7500', '259200', NULL, '0', '0', 'false', '2020-10-31 09:30:30');
INSERT INTO test.oauth_client_details (client_id, resource_ids, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, archived, trusted, autoapprove, create_time) VALUES ('c2', 'res2', '$2a$10$dIONDbZ6k.CHLd6eCJZQS.52LkcutcjJI1CgnsLOl9RNzaPNMaRTS', 'ROLE_API', 'client_credentials,password,authorization_code,implicit,refresh_token', 'http://www.baidu.com', NULL, '31536000', '2592000', NULL, '0', '0', 'false', '2020-10-31 09:27:15');