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客户端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)
@ResponseBody
public 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")
@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();
    //获取 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下载

时间: 2024-08-10 23:18:54

oauth简单使用的相关文章

单点登录系统cas资料汇总

http://jasig.github.io/cas/4.0.x/index.html           主页 https://jasigcas.herokuapp.com                            demo https://wiki.jasig.org/display/CASUM/Home                                 4.x之前的文档 http://jasig.github.io/cas/4.1.x/index.html   

一张图搞定OAuth2.0

1.引言 本篇文章是介绍OAuth2.0中最经典最常用的一种授权模式:授权码模式 非常简单的一件事情,网上一堆神乎其神的讲解,让我不得不写一篇文章来终结它们. 一项新的技术,无非就是了解它是什么,为什么,怎么用.至于为什么,本篇文章不做重点探讨,网上会有各种文章举各种什么丢钥匙.发船票的例子供你去阅读,个人认为还是有些哗众取宠,没有聊到本质. 那我们就重点聊聊OAuth2.0是什么,怎么用.但首先在读本文之前,你要先对OAuth2.0有一定的了解,建议先读一下阮一峰的oauth2.0文章,直接看

第三方QQ登录

原理: OAuth简单原理: 条件:有相应的外网服务和appid.AppKey 申请: 申请appid和appkey: 获取code: 这里可以在本地做测试,把自己的回调地址加入进去就可以了可以localhost,也可以是直接配好的一个本地可以访问的域名也可以 获取官方的SDK: 入门可以先使用官方的SDK,要应用到自己的项目的话可以根据自己的项目做修改,用一个符合自己使用的SDK; 原文地址:https://www.cnblogs.com/yinyusoso/p/9047896.html

拿nodejs快速搭建简单Oauth认证和restful API server攻略

拿nodejs快速搭建简单Oauth认证和restful API server攻略:http://blog.csdn.net/zhaoweitco/article/details/21708955 最近一直在鼓捣这个东西,拿出来分享下一下经验吧,其实很简单,一点也不难. 首先需求是这样,给自己的网站要增加API服务,API分为两种,公共的和私有授权的,授权的使用Oauth方法认证身份,API格式均为JOSN和JSONP. 嗯,别的语言我也没怎么学过,首先是找合适的框架进行实现吧.本身网站使用的e

简单的新浪微博OAuth认证实现

System.setProperty("weibo4j.oauth.consumerKey", Weibo.CONSUMER_KEY); System.setProperty("weibo4j.oauth.consumerSecret", Weibo.CONSUMER_SECRET); Weibo weibo = new Weibo(); // set callback url, desktop app please set to null // http://ca

ScribeJava 3.1.0 发布,简单的 OAuth Java 库

ScribeJava 3.1.0 发布,ScribeJava 是一个简单的 Java 实现的 OAuth/OAuth2 库. 该版本主要改进内容包括: 1. 修复了 OdnoklassnikiServiceImpl 签名,使用词典顺序对参数进行排序后哈希,QKXue.NET找到一个详细的说明 http://new.apiok.ru/dev/methods/ 2. 增加支持使用外部创建的 http 客户端 3. ScribeJava 编译兼容 jdk7 4. 增加 travis CI (check

简单分析第三方登录之oauth认证

关键词:oauth.第三方登录 1.是什么? oauth认证就是一种授权认证机制. 简单分析:用户告诉系统,同意授权第三方应用(eg:本地服务器)进入系统(eg:qq/微信),获取这些数据,系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用,供第三方应用获取系统数据的一种授权认证机制. 2.为什么? 使用这个认证机制可以方便某些用户省去手动注册账号的麻烦,可以直接利用用户已有的信息来自动帮助用户进行注册,为用户带来便利. 3.怎么做? (1)基本流程: 请求用户授权:用

OAuth 2 的简单理解

什么是 OAuth 2.0 根据 oauth.net 的描述,我们可以将它简述为以下内容:OAuth 2.0 是 OAuth 1.0 框架协议的升级版本,简化了多种平台上身份及授权认证的流程. 具体的文档可参考 RFC 6749 和 RFC 6750.  OAuth 2.0 的用途 OAuth 2.0 的主要用途大概有以下几种: 账号接入:降低用户登录的成本.降低一定的账号风险 资源访问:以身份权限为手段保护资源处理的有效性.合法性和安全性  OAuth 2.0 的一般流程 客户端(如 Web

使用OAuth打造webapi认证服务供自己的客户端使用

一.什么是OAuth OAuth是一个关于授权(Authorization)的开放网络标准,目前的版本是2.0版.注意是Authorization(授权),而不是Authentication(认证).用来做Authentication(认证)的标准叫做openid connect,我们将在以后的文章中进行介绍. 二.名词定义 理解OAuth中的专业术语能够帮助你理解其流程模式,OAuth中常用的名词术语有4个,为了便于理解这些术语,我们先假设一个很常见的授权场景: 你访问了一个日志网站(thir