OAuth2 和 SpringSecurity完成授權認證中心(二) 通過jwt令牌,以及JDBC存儲 (有項目源碼)

項目gitee 地址

前面寫了如何配置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);
    }
}

依次啓動 UaaJwtServerOrderJwtServer

使用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

  1. 資源擁有者將用戶名 密碼發給客戶端
  2. 客戶端拿着資源擁有者的用戶名,密碼向服務器請求令牌
  3. 授權服務器將令牌發送給client

參數列表:

  • client_id : 客戶端標識
  • client_secret: 客戶端密鑰
  • grant_tyoe: 授權類型 填寫password 表示 密碼模式
  • username: 用戶名
  • password: 密碼
三、客戶端模式

POST

/uaa/oath/token?grant_type=client_credentials&client_id=c1&client_secret=secret

  1. 客戶端向授權服務器發送自己的身份呢信息,並請求令牌
  2. 確認客戶端身份無誤,將頒發令牌給客戶端

參數列表

  • client_id:客戶端標識
  • client_secret: 客戶端密鑰
  • grant_type: 授權類型, client_credentials 表示客戶端模式
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章