運用Oltu框架搭建OAuth的Demo工程

Apache的Oltu就是實現了OAuth的框架java

參考文章:web

http://jinnianshilongnian.iteye.com/blog/2038646spring

https://blog.csdn.net/jing12062011/article/details/78147306apache

 

1. 搭建Maven工程框架

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.linkedbear</groupId>
      <artifactId>OAuth-Demo</artifactId>
      <version>0.0.1-SNAPSHOT</version>

      <properties>
           <oauth2.version>1.0.2</oauth2.version>
      </properties>

      <parent>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-parent</artifactId>
           <version>2.0.0.RELEASE</version>
      </parent>

      <dependencies>
           <dependency>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-starter-web</artifactId>
           </dependency>
           <!-- OAuth2協議的框架 -->
           <dependency>
                 <groupId>org.apache.oltu.oauth2</groupId>
                 <artifactId>org.apache.oltu.oauth2.client</artifactId>
                 <version>${oauth2.version}</version>
           </dependency>
           <dependency>
                 <groupId>org.apache.oltu.oauth2</groupId>
                 <artifactId>org.apache.oltu.oauth2.common</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.resourceserver</artifactId>
                 <version>${oauth2.version}</version>
           </dependency>
           <!-- 熱部署 -->
           <dependency>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-devtools</artifactId>
           </dependency>
      </dependencies>

      <build>
           <plugins>
                 <plugin>
                      <artifactId>maven-compiler-plugin</artifactId>
                      <configuration>
                            <source>1.8</source>
                            <target>1.8</target>
                      </configuration>
                 </plugin>
           </plugins>
      </build>
</project>

2. 建立工程目錄結構

3. 使用受權碼模式,編寫Controller

3.1 服務消費方

/**
 * 服務消費方Controller層
 * @Title OauthClientController
 * @author LinkedBear
 * @Time 2018年8月1日 下午2:10:14
 */
@Controller
public class OauthClientController {
    //第一步:服務消費方要向用戶申請受權碼
    @RequestMapping("/applyCode")
    public String applyCode(HttpServletRequest request) {
        System.out.println("----------第一步:服務消費方要向用戶申請受權碼-----------");
       
        //第二步的跳轉url(請求Code)
        String accessCodeUrl = "getAuthorization";
        //必填,且固定爲code
        String responseType = "code";
        //必填
        String clientId = "client";
        //第三步要訪問的url
        String redirectUri = "http://localhost:8080/applyToken";
       
        //建立OAuth客戶端對象
        //OAuthClient client = new OAuthClient(new URLConnectionClient());
        //構建OAuth請求
        String locationUri = "";
        try {
            OAuthClientRequest oauthRequest = AuthClientRequest.authorizationLocation(accessCodeUrl)
                    .setRedirectURI(redirectUri)
                    .setClientId(clientId)
                    .setResponseType(responseType)
                    .buildQueryMessage();
            locationUri = oauthRequest.getLocationUri();
            System.out.println("第一步重定向地址:" + locationUri);
        } catch (Exception e) {
            e.printStackTrace();
        }
       
        //重定向
        return "redirect:http://localhost:8080/" + locationUri;
    }
   
   
   
    //第三步:服務消費方要向認證受權服務器發起請求,攜帶本機ID和受權碼
    @RequestMapping("/applyToken")
    public String applyToken(HttpServletRequest request) {
        System.out.println("----------第三步:服務消費方要向認證受權服務器發起請求,攜帶本機ID和受權碼----------");
       
        //第四步的跳轉url(請求Token)
        //關鍵:這裏是要發請求返回json,故不是重定向,在下面沒有url拼接,只能在這裏寫全
        String accessTokenUrl = "http://localhost:8080/getToken";
        String clientId = "client";
        //用於識別客戶端的字段
        String clientSecurt = "clientSecurt";
        //第五步要訪問的url
        String redirectUri = "http://localhost:8080/callbackCode";
       
        String code = request.getParameter("code");
        System.out.println("用戶返回的受權碼:" + code);
       
        //建立OAuth客戶端對象
        OAuthClient client = new OAuthClient(new URLConnectionClient());
        //構建OAuth請求
        String locationUri = "";
        try {
            //這裏的請求由於攜帶了受權碼,而且是請求訪問Token,故調用方法會不一樣
            OAuthClientRequest oauthCodeRequest = OAuthClientRequest.tokenLocation(accessTokenUrl)
                    .setGrantType(GrantType.AUTHORIZATION_CODE)
                    .setRedirectURI(redirectUri)
                    .setClientId(clientId)
                    .setClientSecret(clientSecurt)
                    .setCode(code)
                    .buildQueryMessage();
            locationUri = oauthCodeRequest.getLocationUri();
            System.out.println("第三步重定向地址:" + locationUri);
            //發送請求,並獲得響應
            OAuthJSONAccessTokenResponse tokenResponse = client.accessToken(oauthCodeRequest, HttpMethod.POST);
            //取訪問Token
            String token = tokenResponse.getAccessToken();
            System.out.println("獲得訪問Token:" + token);
            
            //重定向
            return "redirect:http://localhost:8080/applyResource?accessToken=" + token;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
   
   
   
    //第五步:服務消費方持Token訪問請求服務提供方
    @RequestMapping("/applyResource")
    @ResponseBody
    public Map<String, Object> applyResource(String accessToken) {
        System.out.println("----------第五步:服務消費方持Token訪問請求服務提供方-----------");
       
        //真正要請求的資源地址
        String realResourceUrl = "http://localhost:8080/getResource";
       
        //建立OAuth客戶端對象
        OAuthClient client = new OAuthClient(new URLConnectionClient());
        try {
            //構建真正的資源訪問請求,要附帶Token過去
            OAuthClientRequest oauthTokenRequest = new OAuthBearerClientRequest(realResourceUrl)
                    .setAccessToken(accessToken)
                    .buildQueryMessage();
            System.out.println("準備向服務提供方發送請求。。。");
            //請求資源
            OAuthResourceResponse resourceResponse = client.resource(oauthTokenRequest,
                    HttpMethod.GET, OAuthResourceResponse.class);
            String resource = resourceResponse.getBody();
            System.out.println("獲得請求的資源" + resource);
            return JSONUtils.parseJSON(resource);
        } catch (Exception e) {
            return null;
        }
    }
}

3.2 用戶

/**
 * 用戶 Controller層
 * @Title OauthUserController
 * @author LinkedBear
 * @Time 2018年8月1日 下午2:30:29
 */
@Controller
public class OauthUserController {
    public static final String AUTHORIZATION_CODE = "123";
   
    //第二步:用戶收到服務消費方的請求後校驗,作出響應,返回受權碼
    @SuppressWarnings("unused")
    @RequestMapping("/getAuthorization")
    public Object getAuthorization(HttpServletRequest request) {
        System.out.println("----------第二步:用戶收到服務消費方的請求後校驗,作出響應-----------");
       
        try {
            //構建OAuth受權請求
            OAuthAuthzRequest authzRequest = new OAuthAuthzRequest(request);
            //駁回空客戶端請求
            if (StringUtils.isEmpty(authzRequest.getClientId())) {
                return null;
            }
           
            //取responseType,受權碼模式的值固定位"code"
            String responseType = authzRequest.getResponseType();
            //構建OAuth響應,此處必須爲302重定向
            OAuthAuthorizationResponseBuilder responseBuilder =
                    OAuthASResponse.authorizationResponse(request, HttpServletResponse.SC_FOUND);
            //設置受權碼
            responseBuilder.setCode(AUTHORIZATION_CODE);
           
            //獲得服務消費方的重定向地址,並構建OAuth響應
            String redirectUri = authzRequest.getRedirectURI();
            OAuthResponse oauthResponse = responseBuilder.location(redirectUri)
                    .buildQueryMessage();
            //構建完畢後,獲得重定向的url
            String locationUri = oauthResponse.getLocationUri();
            System.out.println("第二步重定向地址:" + locationUri);
           
            return "redirect:" + locationUri;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

3.3 認證受權服務器

/**
 * 認證受權服務器Controller層
 * @Title OauthAuthenticationController
 * @author LinkedBear
 * @Time 2018年8月1日 下午2:10:57
 */
@Controller
public class OauthAuthenticationController {
    //第四步:訪問受權服務器接收服務消費方的請求,校驗並授予訪問Token和更新Token
    @PostMapping("/getToken")
    public ResponseEntity<Object> getToken(HttpServletRequest request) {
        System.out.println("----------第四步:訪問受權服務器接收服務消費方的請求,校驗並授予訪問Token和更新Token-----------");
       
        try {
            //構建OAuth受權請求,此處已有Code
            OAuthTokenRequest authzTokenRequest = new OAuthTokenRequest(request);
            //獲取受權碼
            String code = authzTokenRequest.getCode();
            //受權碼不匹配,直接駁回
            if (!OauthUserController.AUTHORIZATION_CODE.equals(code)) {
                return null;
            }
           
            //生成Token
            OAuthIssuerImpl tokenCreater = new OAuthIssuerImpl(new MD5Generator());
            String token = tokenCreater.accessToken();
            System.out.println("生成Token:" + token);
           
            //構建OAuth響應
            OAuthResponse oauthResponse = OAuthASResponse.tokenResponse(HttpServletResponse.SC_OK)
                    .setAccessToken(token)
                    .setTokenType(TokenType.BEARER.name())
                    .buildJSONMessage();
            //返回的數據是一組json
            return new ResponseEntity<Object>(oauthResponse.getBody(), HttpStatus.valueOf(oauthResponse.getResponseStatus()));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

3.4 服務提供方

/**
 * 服務提供方Controller層
 * @Title OauthServerController
 * @author LinkedBear
 * @Time 2018年8月1日 下午2:09:35
 */
@Controller
public class OauthServerController {
    //第六步:服務提供方驗證Token,返回資源
    @RequestMapping("/getResource")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> getResource(HttpServletRequest request) {
        System.out.println("----------第六步:服務提供方驗證Token,返回資源-----------");
       
        try {
            //最後一步取的是資源,因此構建的請求也不一樣了,並且要附帶一個參數
            OAuthAccessResourceRequest resourceRequest = new OAuthAccessResourceRequest(request, ParameterStyle.QUERY);
            String token = resourceRequest.getAccessToken();
            //這裏還須要驗證Token。。。
            System.out.println("未校驗Token。。。" + token);
           
            Map<String, Object> map = new HashMap<>();
            map.put("data", Math.random());
            map.put("creater", "LinkedBear");
            return new ResponseEntity<Map<String, Object>>(map, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

3.5 運行結果

----------第一步:服務消費方要向用戶申請受權碼-----------

第一步重定向地址:getAuthorization?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2FapplyToken&client_id=client

----------第二步:用戶收到服務消費方的請求後校驗,作出響應-----------

第二步重定向地址:http://localhost:8080/applyToken?code=123

----------第三步:服務消費方要向認證受權服務器發起請求,攜帶本機ID和受權碼-----------

用戶返回的受權碼:123

第三步重定向地址:http://localhost:8080/getToken?code=123&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2FcallbackCode&client_secret=clientSecurt&client_id=client

----------第四步:訪問受權服務器接收服務消費方的請求,校驗並授予訪問Token和更新Token-----------

生成Token:b9bbc794d09cac19f11951972fd7d5b1

獲得訪問Token:b9bbc794d09cac19f11951972fd7d5b1

----------第五步:服務消費方持Token訪問請求服務提供方-----------

準備向服務提供方發送請求。。。

----------第六步:服務提供方驗證Token,返回資源-----------

未校驗Token。。。b9bbc794d09cac19f11951972fd7d5b1

獲得請求的資源{"data":0.08976006535502468,"creater":"LinkedBear"}
相關文章
相關標籤/搜索