oauth簡單使用

一、oauth原理參考

  理解OAuth 2.0

二、本例中采用授權碼模式

  

  大致流程

  (A)用戶訪問客戶端,后者將前者導向認證服務器。
  (B)用戶選擇是否給予客戶端授權。
  (C)假設用戶給予授權,認證服務器將用戶導向客戶端事先指定的"重定向URI"(redirection URI),同時附上一個授權碼。
  (D)客戶端收到授權碼,附上早先的"重定向URI",向認證服務器申請令牌。這一步是在客戶端的后臺的服務器上完成的,對用戶不可見。
  (E)認證服務器核對了授權碼和重定向URI,確認無誤后,向客戶端發送訪問令牌(access token)和更新令牌(refresh token)。

  參數含義

  response_type:表示授權類型,必選項,此處的值固定為"code"
  client_id:表示客戶端的ID,必選項
  redirect_uri:表示重定向URI,可選項
  scope:表示申請的權限范圍,可選項,本例中無
  state:表示客戶端的當前狀態,可以指定任意值,認證服務器會原封不動地返回這個值,本例中無

三、項目中依賴oauth相關jar

<!-- oauth -->
<dependency><groupId>org.apache.oltu.oauth2</groupId><artifactId>org.apache.oltu.oauth2.resourceserver</artifactId><version>${oauth2-version}</version>
</dependency>
<dependency><groupId>org.apache.oltu.oauth2</groupId><artifactId>org.apache.oltu.oauth2.authzserver</artifactId><version>${oauth2-version}</version>
</dependency>
<dependency><groupId>org.apache.oltu.oauth2</groupId><artifactId>org.apache.oltu.oauth2.client</artifactId><version>${oauth2-version}</version>
</dependency>

四、獲取授權碼

/*** 獲取授權碼-服務端** @param request* @return* @throws OAuthProblemException* @throws OAuthSystemException*/
@RequestMapping(value = "/authorize", method = RequestMethod.GET)
@ResponseBody
public Object authorize(HttpServletRequest request) throws URISyntaxException, OAuthProblemException, OAuthSystemException {try {// 構建OAuth授權請求OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request);// 1.獲取OAuth客戶端idString clientId = oauthRequest.getClientId();// 校驗客戶端id是否正確LightUserResult lightUserResult = userApi.queryUserByClientId(clientId);if (null == lightUserResult) {OAuthResponse response =OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST).setError(OAuthError.TokenResponse.INVALID_CLIENT).setErrorDescription("無效的客戶端ID").buildJSONMessage();return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));}// 2.生成授權碼String authCode = null;String responseType = oauthRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE);// ResponseType僅支持CODE和TOKENif (responseType.equals(ResponseType.CODE.toString())) {OAuthIssuerImpl oAuthIssuer = new OAuthIssuerImpl(new MD5Generator());authCode = oAuthIssuer.authorizationCode();// 存入緩存中authCode-username
            RedisUtil.getRedis().set(authCode, lightUserResult.getUserName());}return new ResponseEntity(authCode, HttpStatus.OK);} catch (Exception e) {return new ResponseEntity("內部錯誤", HttpStatus.valueOf(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));}
}

五、根據授權碼獲取token

/*** 獲取訪問令牌** @param request* @return* @throws OAuthProblemException* @throws OAuthSystemException*/
@RequestMapping(value = "accessToken", method = RequestMethod.POST)
@ResponseBody
public Object accessToken(HttpServletRequest request) throws OAuthProblemException, OAuthSystemException {try {// 構建OAuth請求OAuthTokenRequest tokenRequest = new OAuthTokenRequest(request);// 1.獲取OAuth客戶端idString clientId = tokenRequest.getClientId();// 校驗客戶端id是否正確LightUserResult lightUserResult = userApi.queryUserByClientId(clientId);if (null == lightUserResult) {OAuthResponse oAuthResponse = OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST).setError(OAuthError.TokenResponse.INVALID_CLIENT).setErrorDescription("無效的客戶端ID").buildJSONMessage();return new ResponseEntity(oAuthResponse.getBody(), HttpStatus.valueOf(oAuthResponse.getResponseStatus()));}// 2.檢查客戶端安全key是否正確if (!lightUserResult.getClientSecret().equals(tokenRequest.getClientSecret())) {OAuthResponse oAuthResponse = OAuthResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED).setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT).setErrorDescription("客戶端安全key認證不通過").buildJSONMessage();return new ResponseEntity<>(oAuthResponse.getBody(), HttpStatus.valueOf(oAuthResponse.getResponseStatus()));}// 3.檢查授權碼是否正確String authCode = tokenRequest.getParam(OAuth.OAUTH_CODE);// 檢查驗證類型,此處只檢查AUTHORIZATION_CODE類型,其他的還有password或REFRESH_TOKENif (!tokenRequest.getParam(OAuth.OAUTH_GRANT_TYPE).equals(GrantType.AUTHORIZATION_CODE.toString())) {if (null == RedisUtil.getRedis().get(authCode)) {OAuthResponse response = OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST).setError(OAuthError.TokenResponse.INVALID_GRANT).setErrorDescription("授權碼錯誤").buildJSONMessage();return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));}}// 4.生成訪問令牌Access TokenOAuthIssuer oAuthIssuer = new OAuthIssuerImpl(new MD5Generator());final String accessToken = oAuthIssuer.accessToken();// 將訪問令牌加入緩存:accessToken-username
        RedisUtil.getRedis().set(accessToken, lightUserResult.getUserName());// 5.生成OAuth響應OAuthResponse response = OAuthASResponse.tokenResponse(HttpServletResponse.SC_OK).setAccessToken(accessToken).setExpiresIn(expiresIn).buildJSONMessage();return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));} catch (Exception e) {e.printStackTrace();return new ResponseEntity("內部錯誤", HttpStatus.valueOf(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));}}

?六、簡單測試

@RequestMapping("authority")
@ResponseBody
public JSONObject authority() throws OAuthSystemException, OAuthProblemException {JSONObject result = new JSONObject();OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());OAuthClientRequest codeTokenRequest = OAuthClientRequest.authorizationLocation("http://127.0.0.1:8080/auth-web/oauth/authorize").setResponseType(ResponseType.CODE.toString()).setClientId("c1ebe466-1cdc-4bd3-ab69-77c3561b9dee").buildQueryMessage();//獲取 codeOAuthResourceResponse codeResponse = oAuthClient.resource(codeTokenRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);if(codeResponse.getResponseCode() != HttpServletResponse.SC_OK) {result.put("code", codeResponse.getResponseCode());result.put("msg", codeResponse.getBody());} else {String authCode = codeResponse.getBody();OAuthClientRequest accessTokenRequest = OAuthClientRequest.tokenLocation("http://127.0.0.1:8080/auth-web/oauth/accessToken").setGrantType(GrantType.AUTHORIZATION_CODE).setClientId("c1ebe466-1cdc-4bd3-ab69-77c3561b9dee").setClientSecret("d8346ea2-6017-43ed-ad68-19c0f971738b").setCode(authCode).setRedirectURI("http://127.0.0.1:8080/auth-web/").buildQueryMessage();//獲取access tokenOAuthAccessTokenResponse tokenResponse =oAuthClient.accessToken(accessTokenRequest, OAuth.HttpMethod.POST);if(tokenResponse.getResponseCode() != HttpServletResponse.SC_OK) {result.put("code", tokenResponse.getResponseCode());result.put("msg", tokenResponse.getBody());return result;} else {//驗證tokenOAuthClientRequest validateRequest =new OAuthBearerClientRequest("http://127.0.0.1:8080/auth-web/oauth/validate").setAccessToken(tokenResponse.getAccessToken()).buildQueryMessage();OAuthResourceResponse validateResponse = oAuthClient.resource(validateRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);if(validateResponse.getResponseCode() != HttpServletResponse.SC_OK) {result.put("code", validateResponse.getResponseCode());result.put("msg", validateResponse.getBody());} else {JSONObject body = JSON.parseObject(validateResponse.getBody());result.put("code", body.getString("code"));result.put("msg", body.getString("msg"));}}}return result;
}
public static ResponseEntity oauthValidate(HttpServletRequest request) throws OAuthProblemException, OAuthSystemException {// 構建OAuth資源請求OAuthAccessResourceRequest resourceRequest = new OAuthAccessResourceRequest(request, ParameterStyle.QUERY);// 獲取訪問令牌access TokenString accessToken = resourceRequest.getAccessToken();// 驗證訪問令牌if (null == RedisUtil.getRedis().get(accessToken)) {// 如果不存在或過期了,返回未驗證錯誤,需重新驗證OAuthResponse response = OAuthRSResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED).setError(OAuthError.ResourceResponse.INVALID_TOKEN).setErrorDescription("訪問令牌不存在或已過期,請重新驗證").buildJSONMessage();return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));}return new ResponseEntity("驗證成功", HttpStatus.valueOf(HttpServletResponse.SC_OK));
}

七、項目地址

  oauth認證demo下載

轉載于:https://www.cnblogs.com/hujunzheng/p/7126766.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/531250.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/531250.shtml
英文地址,請注明出處:http://en.pswp.cn/news/531250.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

我眼中的服務提供和服務消費

服務提供和消費腦圖 服務提供和消費腦圖 參見: 服務提供者, 服務消費者, 服務注冊中心 服務提供者 1.服務提供者啟動&#xff0c;解析xml文件中配置的服務&#xff0c;這里使用Dom4j解析。 2.將服務的一些相關信息注冊到 服務注冊中心。 注&#xff1a;服務相關信息&#xff1a…

shiro整合oauth

前言 如果oauth原理還不清楚的地方&#xff0c;其參考這里。 一、基本思路腦圖 二、客戶端shiro配置 shiro配置文件 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:util&q…

springmvc+swagger2

一、swagger2依賴 <!--swagger--> <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><exclusions><exclusion><artifactId>spring-aop</artifactId><groupId>org.s…

獲取資源文件工具類

如果沒有依賴spring&#xff0c;可以將分割線下的方法去掉 import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframe…

無狀態shiro認證組件(禁用默認session)

準備內容 簡單的shiro無狀態認證 無狀態認證攔截器 import com.hjzgg.stateless.shiroSimpleWeb.Constants; import com.hjzgg.stateless.shiroSimpleWeb.realm.StatelessToken; import org.apache.shiro.web.filter.AccessControlFilter;import javax.servlet.ServletRequest;…

Spring根據包名獲取包路徑下的所有類

參考mybatis MapperScannerConfigurer.java 最終找到 Spring的一個類 ClassPathBeanDefinitionScanner.java 參考ClassPathBeanDefinitionScanner 和它的父類 ClassPathScanningCandidateComponentProvider&#xff0c;將一些代碼進行抽取&#xff0c;得到如下工具類。 import…

java8 Optional正確使用姿勢

Java 8 如何正確使用 Optional import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; import org.apache.commons.lang3.StringUtils;import java.util.Optional;Data EqualsAndHashCode(exclude{"self"}) ToString(callSupertrue, exclud…

idea springboot熱部署無效問題

Intellij IDEA 使用Spring-boot-devTools無效解決辦法 springboot項目中遇到的bug <dependencies><!--spring boot 熱加載--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId&g…

lintcode 單詞接龍II

題意 給出兩個單詞&#xff08;start和end&#xff09;和一個字典&#xff0c;找出所有從start到end的最短轉換序列 比如&#xff1a; 1、每次只能改變一個字母。 2、變換過程中的中間單詞必須在字典中出現。 注意事項 所有單詞具有相同的長度。所有單詞都只包含小寫字母。樣例…

lintcode 最大子數組III

題目描述 給定一個整數數組和一個整數 k&#xff0c;找出 k 個不重疊子數組使得它們的和最大。每個子數組的數字在數組中的位置應該是連續的。 返回最大的和。 注意事項 子數組最少包含一個數 樣例 給出數組 [-1,4,-2,3,-2,3] 以及 k 2&#xff0c;返回 8 思路 dp[i][j] max(…

idea模板注釋

類文件頭部的注釋 #if (${PACKAGE_NAME} && ${PACKAGE_NAME} ! "")package ${PACKAGE_NAME};#end #parse("File Header.java") /** * ${DESCRIPTION} * author ${USER} hujunzheng * create ${YEAR}-${MONTH}-${DAY} ${TIME} **/ public class ${N…

redis分布式鎖小試

一、場景 項目A監聽mq中的其他項目的部署消息&#xff08;包括push_seq, status, environment&#xff0c;timestamp等&#xff09;&#xff0c;然后將部署消息同步到數據庫中&#xff08;項目X在對應環境[environment]上部署的push_seq[項目X的版本]&#xff09;。那么問題來了…

Jackson ObjectMapper readValue過程

1.整體調用棧 2.看一下調用棧的兩個方法 resolve 方法中通過 Iterator i$ this._beanProperties.iterator() 遍歷屬性的所有子屬性&#xff0c;緩存對應的 deserializer。觀察調用棧的方法&#xff0c;可以發現是循環調用的。 3.比如尋找自定義的 LocalDateTime類的序列化實現…

java如何尋找main函數對應的類

參考springboot Class<?> deduceMainApplicationClass() {try {StackTraceElement[] stackTrace new RuntimeException().getStackTrace();for (StackTraceElement stackTraceElement : stackTrace) {if ("main".equals(stackTraceElement.getMethodName())…

jooq實踐

用法 sql語句 SELECT AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, COUNT(*)FROM AUTHORJOIN BOOK ON AUTHOR.ID BOOK.AUTHOR_IDWHERE BOOK.LANGUAGE DEAND BOOK.PUBLISHED > DATE 2008-01-01 GROUP BY AUTHOR.FIRST_NAME, AUTHOR.LAST_NAMEHAVING COUNT(*) > 5 ORDER BY AUT…

不同包下,相同數據結構的兩個類進行轉換

import com.alibaba.fastjson.JSON; JSON.parseObject(JSON.toJSONString(obj1), obj2.class) import com.fasterxml.jackson.databind.ObjectMapper; objectMapper.convertValue(obj1, obj2.class); 兩個工具類 JsonUtil JacksonHelper 轉載于:https://www.cnblogs.com/hujunz…

git根據用戶過濾提交記錄

使用SourceTree 使用gitk 轉載于:https://www.cnblogs.com/hujunzheng/p/8398203.html

springboot Autowired BeanNotOfRequiredTypeException

現象 org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named xxxxImpl is expected to be of type com.xxx.xxxImpl but was actually of type com.sun.proxy.$Proxy62 直接Autowired一個實現類&#xff0c;而不是接口 Autowired private XxxServiceI…

cglib動態代理導致注解丟失問題及如何修改注解允許被繼承

現象 SOAService這個bean先后經過兩個BeanPostProcessor&#xff0c;會發現代理之后注解就丟失了。 開啟了cglib代理 SpringBootApplication EnableAspectJAutoProxy(proxyTargetClass true) public class Application {public static void main(String[] args) {SpringApplic…

spring AbstractBeanDefinition創建bean類型是動態代理類的方式

1.接口 Class<?> resourceClass 2.獲取builder BeanDefinitionBuilder builder BeanDefinitionBuilder.genericBeanDefinition(resourceClass); 3.獲取接口對應的動態代理class Class<?> targetProxyClass Proxy.getProxyClass(XXX.class.getClassLoader(), ne…