如何用Spring OAuth2.0 Client元件獲取授權access_token
阿新 • • 發佈:2019-01-28
使用背景 :公司有個開放平臺,若要訪問開放平臺,必須先要獲取授權訪問令牌(也就是下面說的:access_token)。公司的授權系統是用spring oauth2.0實現的,今天就不講這個專案,網上比較多。今天主要是講下如何用spring OAuth2.0 Client 元件會去實現高效獲取access_token。
以下是實現程式碼:
1.專案啟動後,從oauth.properties獲取相關的資訊(如公鑰、私鑰等資訊),然後例項化OAuth2RestTemplate,主要是通過OAuth2RestTemplate這個類去獲取access_token,.
@EnableOAuth2Client @Configuration @Component public class Oauth2Config{ private final static Logger logger = Logger.getLogger(Oauth2Config.class); private static String location = "classpath:config/*/oauth.properties"; private static Map<String,String> oauthInfo = new HashMap<String,String>(); @Autowired private OAuth2ClientContext oauth2Context; /** * 獲取配置檔案資訊 */ static{ ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver(); Resource[] resources; try { resources = patternResolver.getResources(location); location = resources[0].getFile().getAbsolutePath(); logger.info("location" + location); Properties props = new Properties(); try { if(location.contains("dev")){ props = PropertiesLoaderUtils.loadAllProperties("config/dev/oauth.properties"); }else if(location.contains("test")){ props = PropertiesLoaderUtils.loadAllProperties("config/test/oauth.properties"); }else if(location.contains("production")){ props = PropertiesLoaderUtils.loadAllProperties("config/production/oauth.properties"); } for(Object key:props.keySet()){ logger.warn(key + " : " + (String)props.get(key)); oauthInfo.put((String) key, (String)props.get(key)); } } catch (IOException e) { System.out.println(e.getMessage()); } } catch (IOException e) { e.printStackTrace(); } } @Bean public AccessTokenRequest accessTokenRequest(){ AccessTokenRequest defaultAccessTokenRequest = new DefaultAccessTokenRequest(); Map<String, List<String>> headers = new HashMap<String, List<String>>(); List<String> headerList=new ArrayList<String>(); headerList.add("Basic " + oauthInfo.get("public_key")); headers.put("Authorization", headerList); defaultAccessTokenRequest.setHeaders(headers); defaultAccessTokenRequest.setCurrentUri(oauthInfo.get("redirect_uri")); return defaultAccessTokenRequest; } @Bean public AuthorizationCodeResourceDetails resourceDetails(){ AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails(); resource.setAccessTokenUri(oauthInfo.get("oauth_url") + oauthInfo.get("request_and_refresh_token")); resource.setClientId(oauthInfo.get("client_id")); resource.setGrantType("authorization_code"); resource.setUserAuthorizationUri(oauthInfo.get("oauth_url") + oauthInfo.get("request_code_url")); resource.setScope(Arrays.asList("app")); resource.setPreEstablishedRedirectUri(oauthInfo.get("redirect_uri")); return resource; } @Bean public OAuth2RestTemplate oAuth2RestTemplate(){ accessTokenRequest().setPreservedState(oauthInfo.get("redirect_uri")); accessTokenRequest().setStateKey(new DefaultStateKeyGenerator().generateKey(resourceDetails())); AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider(); provider.setAuthenticationHandler(new ClientAuthenticationHandler() { @Override public void authenticateTokenRequest( OAuth2ProtectedResourceDetails resource, MultiValueMap<String, String> form, HttpHeaders headers) { headers.set("Authorization", "Basic " + oauthInfo.get("private_key") ); } }); AccessTokenProviderChain providerChain = new AccessTokenProviderChain(Arrays.asList(provider)); //oauth2Context.setPreservedState(accessTokenRequest().getStateKey(),accessTokenRequest().getPreservedState()); OAuth2RestTemplate template=new OAuth2RestTemplate(resourceDetails(),oauth2Context); template.setAccessTokenProvider(providerChain); return template; } }
2.通過OAuth2RestTemplate去獲取access_token的值,之所以每次都情況授權code,是因為spring oauth2授權code只能用一次便廢棄,然後起OAuth2ClientContext類又不主動清空code,這裡我只能自己手動清除。
@Component public class AccessTokenUtils { private final static Logger logger = Logger.getLogger(AccessTokenUtils.class); @Autowired private OAuth2RestTemplate restTemplate; @Autowired private Oauth2Config oauth2Config; /** * 獲取oauth2的授權令牌access_token * @return */ public String getAccessToken(){ logger.info("獲取oauth2的授權令牌access_token start ..."); OAuth2ClientContext oAuth2ClientContext = restTemplate.getOAuth2ClientContext(); oAuth2ClientContext.getAccessTokenRequest().setAuthorizationCode(null);//清空授權code String stateKey = oAuth2ClientContext.getAccessTokenRequest().getStateKey(); Object preservedState = oAuth2ClientContext.getAccessTokenRequest().getPreservedState(); if(StringUtils.isEmpty(stateKey)) stateKey = new DefaultStateKeyGenerator().generateKey(oauth2Config.resourceDetails()); if(preservedState == null ) preservedState = VipConstant.redirtUrl; logger.info("statekey:" + stateKey + " ; preservedState : " + preservedState); oAuth2ClientContext.setPreservedState(oAuth2ClientContext.getAccessTokenRequest().getStateKey(), oAuth2ClientContext.getAccessTokenRequest().getPreservedState()); OAuth2AccessToken oAuth2AccessToken = this.restTemplate.getAccessToken(); String access_token = oAuth2AccessToken.getValue(); logger.info("獲取oauth2的授權令牌access_token end ;access_token = " + access_token + ";失效時間 = " + oAuth2AccessToken.getExpiration() + " ;剩餘失效時間:" + oAuth2AccessToken.getExpiresIn() ); return access_token; } }
3.以下配置是授權服務給配置的
#==================spring oauth2.0===================================== #客戶端ID client_id=xxx #公鑰(BASE64(xx)) public_key=xxx #私鑰(BASE64(xx)) private_key=xx #spring oauth2.0服務url oauth_url=xxx #獲取請求code URL request_code_url=oauth/authorize #獲取請求token或重新整理token URL request_and_refresh_token=oauth/token #回撥地址 redirect_uri=http://www.baidu.com
Spring OAuth2.0 Client官網地址:http://projects.spring.io/spring-security-oauth/docs/oauth2.html