一、添加依賴
在這里我們也需要導入redis的相關依賴,因為實際使用過程,需要人為干預令牌的有效時間
<!--Oauth2依賴--> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>${security-oauth2-version}</version> </dependency> <!--使用jwt令牌--> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-jwt</artifactId> <version>${jwt-version}</version> </dependency> <!-- 配置使用redis啟動器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>${redis-jedis-version}</version> </dependency> <!--fastjson轉換--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${alibaba-fastjon-version}</version> </dependency>
二、生成jks證書
在導入依賴包后, 我們需要再redsources文件下創建配置文件application.yml,在這里我們不做過多的說明,我們要使用到JWT安全證書,並通過證書生成令牌,並將生成的證書文件xxx.jks放到resources文件下。
三、創建SecurityConfiguration.java實體類,並讓其繼承WebSecurityConfigurerAdapt,其中myUserDetailsServiceImpl是進行驗證登陸者賬號和密碼的實體類
@Configuration @EnableWebSecurity class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter { @Resource(name = "myUserDetailsServiceImpl") private UserDetailsService userDetailsService; @Override public void configure(WebSecurity web) throws Exception { //用戶登錄認證、用戶退出、用戶獲取jwt令牌 web.ignoring().antMatchers("/XXX"); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { AuthenticationManager manager = super.authenticationManagerBean(); return manager; } @Override protected UserDetailsService userDetailsService() { return userDetailsService; } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService); } //采用bcrypt對密碼進行編碼 @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override public void configure(HttpSecurity http) throws Exception { // http.csrf().disable() // .httpBasic().and() // .formLogin() // .and() // .authorizeRequests().anyRequest().authenticated(); http.authorizeRequests().anyRequest().permitAll().and().csrf().disable(); } }
四、UserDetailsServiceImpl實體類,我們可以看到這里做了賬號密碼驗證並且使用了加密
五、創建實體類AuthServerConfig.java實體類,該實體類做了關於oauth2客戶端的一些配置
@Configuration @EnableAuthorizationServer public class CustomAuthServerConfig extends AuthorizationServerConfigurerAdapter { /*jwt令牌轉換器*/ @Autowired private JwtAccessTokenConverter jwtAccessTokenConverter; /*在這里userDetailService一定要加上@Autowired,否則會報錯找不到服務器UserDetailsService is required*/ @Resource(name = "myUserDetailsServiceImpl") UserDetailsService userDetailsService; @Autowired AuthenticationManager authenticationManager; @Autowired TokenStore tokenStore; @Autowired PasswordEncoder passwordEncoder; @Autowired private SecurityAuth securityAuth; /* 授權服務器的安全配置*/ @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer .tokenKeyAccess("permitAll()") .allowFormAuthenticationForClients() /*校驗token需要認證通過,可采用http basic認證*/ .checkTokenAccess("isAuthenticated()"); } /*設置認證請求相關參數,例如客戶端賬號和密碼、令牌有效時間等等*/ @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient(securityAuth.getClientId())/*客戶端id*/ .secret(passwordEncoder.encode(securityAuth.getClientSecret()))/*密碼,要保密*/ .accessTokenValiditySeconds(60 * 60 * X)/*訪問令牌有效期X個小時*/
.refreshTokenValiditySeconds(60 * 60 * X)/*刷新令牌有效期X個小時*/
/*授權客戶端請求認證服務的類型authorization_code:根據授權碼生成令牌, client_credentials:客戶端認證,refresh_token:刷新令牌,password:密碼方式認證*/ .authorizedGrantTypes("authorization_code", "client_credentials", "refresh_token", "password") .redirectUris("http://localhost") .scopes("app");/*客戶端范圍,名稱自定義,必填*/ } @Bean public TokenEnhancer customTokenEnhancer() { return new CustomTokenEnhancer(); } /*授權服務器端點配置*/ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { /*endpoints.authenticationManager(authenticationManager)認證管理器 .userDetailsService(userDetailsService);/*用戶信息service*/ /*將增強的token設置到增強鏈中*/ TokenEnhancerChain enhancerChain = new TokenEnhancerChain(); enhancerChain.setTokenEnhancers(Arrays.asList(customTokenEnhancer(), jwtAccessTokenConverter())); endpoints.accessTokenConverter(jwtAccessTokenConverter) .authenticationManager(authenticationManager)/*認證管理器*/ .tokenStore(tokenStore)/*令牌存儲*/ .userDetailsService(userDetailsService)/*用戶信息service*/ .tokenEnhancer(enhancerChain);//自定義jwt令牌中的攜帶參數 } //使用證書文件生成jwt令牌的 @Bean @Autowired public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) { return new JwtTokenStore(jwtAccessTokenConverter); } @Bean public JwtAccessTokenConverter jwtAccessTokenConverter() { /* 證書文件*/ String key_location = "XXXX.jks";
/*密鑰庫密碼*/ String keystore_password = "XXXX";
/*訪問證書路徑*/ ClassPathResource resource = new ClassPathResource(key_location); /*密鑰工廠*/ KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resource, keystore_password.toCharArray()); /*密鑰別名*/ String alias = "XXXX";
/*密鑰庫密碼*/ String keypassword = "XXXX"; KeyPair keyPair = keyStoreKeyFactory.getKeyPair(alias, keypassword.toCharArray()); JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); converter.setKeyPair(keyPair); return converter; } }
這樣認證服務器的配置參數就完成了,啟動服務后,我們就可以測試發送驗證請求,因為在這里我們僅僅敘述的是功能的實現,賬號密碼都用一些最簡單的,這塊的業務邏輯,可以根據實際情況去編寫,是否能獲取到返回的令牌
六、測試
密碼模式測試
Post請求:http://localhost:8080/oauth/token
參數:
grant_type:密碼模式授權填寫password
username:賬號
password:密碼
此鏈接需要使用http Basic認證,這點需要注意以下,http Basic中認證信息的username和password就寫我們之前在代碼中預先寫好的內容
access_token:訪問令牌,攜帶此令牌訪問資源
token_type:在請求資源的時候,在令牌之前加上該信息,並且空一格
refresh_token:刷新令牌,使用此令牌可以延長訪問令牌的過期時間
expires_in:過期時間,單位為秒
scope:范圍,與定義的客戶端范圍一致
看到以上信息的時候,恭喜你測試成功!