首页 > 代码库 > oauth简单使用

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)@ResponseBodypublic Object authorize(HttpServletRequest request) throws URISyntaxException, OAuthProblemException, OAuthSystemException {    try {        // 构建OAuth授权请求        OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request);        // 1.获取OAuth客户端id        String 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和TOKEN        if (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)@ResponseBodypublic Object accessToken(HttpServletRequest request) throws OAuthProblemException, OAuthSystemException {    try {        // 构建OAuth请求        OAuthTokenRequest tokenRequest = new OAuthTokenRequest(request);        // 1.获取OAuth客户端id        String 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_TOKEN        if (!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 Token        OAuthIssuer 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")@ResponseBodypublic 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();    //获取 code    OAuthResourceResponse 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 token        OAuthAccessTokenResponse 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 {            //验证token            OAuthClientRequest 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 Token    String 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下载

oauth简单使用