认证中心:【Security(登录)+Oauth2(颁发授权码/Token)+JWT(加密Token)】
资源服务器:Oauth2+JWT(解密Token)校验Token+security
2.1.导入依赖
spring-cloud-starter-oauth2 整合了Security ,Oauth2, JWT
-
-
org.springframework.cloud -
spring-cloud-starter-oauth2 -
2.2.改造Security配置
【注意】这里需要在Security配置类中配置一个AuthenticationManager,因为Oauth2的password模式会使用到
- //配置认证管理器,授权模式为“poassword”时会用到
- @Bean
- public AuthenticationManager authenticationManager() throws Exception {
- return super.authenticationManager();
- }
2.3.Oauth2授权服务配置
- package cn.wmx.mooccc.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.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.client.JdbcClientDetailsService;
- 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;
- import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
-
- import javax.sql.DataSource;
- import java.util.Arrays;
- /**
- * 授权服务配置
- * */
- @Configuration
- //开启授权服务配置
- @EnableAuthorizationServer
- public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
-
- //1.客户端详情配置(请求参数)
- @Autowired
- private DataSource dataSource ;
-
- @Autowired
- private PasswordEncoder passwordEncoder ;
-
- //1.1.注册客户端详情Bean,基于数据库,自动操作表:oauth_client_details
- @Bean
- public JdbcClientDetailsService jdbcClientDetailsService(){
- JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
- //数据库的秘钥使用了PasswordEncoder加密
- jdbcClientDetailsService.setPasswordEncoder(passwordEncoder);
- return jdbcClientDetailsService;
- }
- @Override
- public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
- clients.withClientDetails(jdbcClientDetailsService());
- }
-
- //2.授权服务端点配置(授权码,令牌)
-
- @Autowired
- private AuthenticationManager authenticationManager ;
-
- //2.1.定义授权码服务,连接数据库 oauth_code
- @Bean
- public JdbcAuthorizationCodeServices jdbcAuthorizationCodeServices(){
- return new JdbcAuthorizationCodeServices(dataSource);
- }
- //2.2.令牌服务配置
- //令牌的管理服务
- @Bean
- public AuthorizationServerTokenServices tokenService(){
- //创建默认的令牌服务
- DefaultTokenServices services = new DefaultTokenServices();
- //指定客户端详情配置
- services.setClientDetailsService(jdbcClientDetailsService());
- //支持产生刷新token
- services.setSupportRefreshToken(true);
- //token存储方式
- services.setTokenStore(tokenStore());
-
- //设置token增强 - 设置token转换器
- TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
- tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter()));
- services.setTokenEnhancer(tokenEnhancerChain); //jwtAccessTokenConverter()
-
- return services;
- }
-
- //2.3.配置Token的存储方案
- //基于内存的Token存储
- @Bean
- public TokenStore tokenStore(){
- //return new InMemoryTokenStore();
- return new JwtTokenStore(jwtAccessTokenConverter());
- }
-
- //2.4.配置令牌转换器 ,设置JWT签名密钥。它可以是简单的MAC密钥,也可以是RSA密钥
- private final String sign_key = "123";
-
- //JWT令牌校验工具
- @Bean
- public JwtAccessTokenConverter jwtAccessTokenConverter(){
- JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
- //设置JWT签名密钥。它可以是简单的MAC密钥,也可以是RSA密钥
- jwtAccessTokenConverter.setSigningKey(sign_key);
- return jwtAccessTokenConverter;
- }
-
- @Override
- public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
- endpoints
- //1.密码授权模式需要 密码模式,需要认证管理器
- .authenticationManager(authenticationManager)
- //2.授权码模式服务
- .authorizationCodeServices(jdbcAuthorizationCodeServices())
- //3.配置令牌管理服务
- .tokenServices(tokenService())
- //允许post方式请求
- .allowedTokenEndpointRequestMethods(HttpMethod.POST);
- }
-
- //2.授权服务安全配置(URL放行)
- @Override
- public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
- security
- //对应/oauth/check_token ,路径公开
- .checkTokenAccess("permitAll()")
- //允许客户端进行表单身份验证,使用表单认证申请令牌
- .allowFormAuthenticationForClients();
- }
-
- }
作用分别如下:
ClientDetailsServiceConfigurer :用来配置客户端详情服务:如配置客户端id(client_id)资源id、客户端密钥(secrect)、授权方式、scope等,可以基于内存或jdbc。(可以理解为是对浏览器向授权服务器获取授权码或令牌时需要提交的参数配置)
AuthorizationServerEndpointsConfigurer:配置令牌的访问端点url和令牌服务,如配置如何管理授权码(内存或jdbc),如何管理令牌(存储方式,有效时间等等)
AuthorizationServerSecurityConfigurer: 用来配置令牌端点的安全约束,如配置对获取授权码,检查token等某些路径进行放行
2.4.测试
1.授权码模式测试
浏览器,使用账号密码登录 【数据库中的数据】

登录成功后访问
访问如下地址获取授权码 , 注意修改端口和其他参数
http://localhost:10040/oauth/authorize?client_id=admin&response_type=code&redirect_uri=http://www.baidu.com
注意这里的client_id对应的值是数据库中的值

点击approve 批准【这个步骤就是为了获取授权码code】

再使用Postmain获取Token , 注意修改端口和其他参数 【这个步骤就是为了获取access_token,里面包含了用户的信息】
- Url: http://localhost:10040/oauth/token?
- client_id=admin&client_secret=123&grant_type=authorization_code&code=3mlI1z&redirect_uri=http://www.baidu.com
注意client_id和clien_secret都是数据库对应的数据

记得修改里面的code【code就是前面生成的code】
然后获取到access_token,里面包含了用户的信息

2.校验token【获取token中包含的信息】
访问如下地址校验Token , token值改成自己的Token
http://localhost:10040/oauth/check_token?token=【上面获取的access_token】
