一、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下载

oauth简单使用的更多相关文章

  1. 基于 OAuth 安全协议的 Java 应用编程1

    原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-oauth/index.html 參考博客:http://www.cnblogs.com/wan ...

  2. 单点登录 之 OAuth

    OAuth2.0是什么 OAuth2.0是什么——豆瓣和QQ的故事 OAuth简单说就是一种授权的协议,只要授权方和被授权方遵守这个协议去写代码提供服务,那双方就是实现了OAuth模式. 举个例子,你 ...

  3. 简单搞懂OAuth2.0

    本文转自:https://www.cnblogs.com/flashsun/p/7424071.html 原作者:闪客sun 一张图搞定OAuth2.0 目录 1.引言 2.OAuth2.0是什么 3 ...

  4. 秒懂OAuth2.0

    1.引言 本篇文章是介绍OAuth2.0中最经典最常用的一种授权模式:授权码模式 非常简单的一件事情,网上一堆神乎其神的讲解,让我不得不写一篇文章来终结它们. 一项新的技术,无非就是了解它是什么,为什 ...

  5. 一张图搞定OAuth2.0

    1.引言 本篇文章是介绍OAuth2.0中最经典最常用的一种授权模式:授权码模式 非常简单的一件事情,网上一堆神乎其神的讲解,让我不得不写一篇文章来终结它们. 一项新的技术,无非就是了解它是什么,为什 ...

  6. 2018/04/14 理解oAuth2.0

    最近都近没有更新博客了,卡在 oAuth 上了. 之前公司做统一身份的认证,不了解 oAuth 的我在这卡了两天. 于是决定仔细研究原理,理论指导实践. -- 什么是 oAuth ? 简单来说 oAu ...

  7. 单点登录系统cas资料汇总

    http://jasig.github.io/cas/4.0.x/index.html           主页 https://jasigcas.herokuapp.com              ...

  8. 一张图搞定OAuth2.0 在Office应用中打开WPF窗体并且让子窗体显示在Office应用上 彻底关闭Excle进程的几个方法 (七)Net Core项目使用Controller之二

    一张图搞定OAuth2.0   目录 1.引言 2.OAuth2.0是什么 3.OAuth2.0怎么写 回到顶部 1.引言 本篇文章是介绍OAuth2.0中最经典最常用的一种授权模式:授权码模式 非常 ...

  9. Auth2.0 例子【转载】

    本文转载自:https://www.cnblogs.com/flashsun/p/7424071.html 1.引言 本篇文章是介绍OAuth2.0中最经典最常用的一种授权模式:授权码模式 非常简单的 ...

随机推荐

  1. VR全景加盟-全景智慧城市携万千创业者决战BAT

    在所谓互联网思维走到末路.可穿戴设备基本昙花一现的大环境下,很多互联网人员转战VR市场,自然喜欢用互联网思维来考虑.笔者认识一些投资界人士,在谈到投资时,他们经常就问以下几句话:2B还是2C?将来有多 ...

  2. CNPM 遇到use strict的问题

    一.问题描述 [root@VM_123_144_centos node01]# cnpm install --save nodemailer /usr/lib/node_modules/cnpm/no ...

  3. 关于DB2死锁处理

    昨天在修改字段类型的时候引起了死锁,我一般会使用REORG命令处理,在控制中心下 只需要执行 REORG TABLE TABLENAME  命令就可以, 但是在 RazorSQL 下执行此命令会报缺失 ...

  4. 【转】HTTP长连接与短连接(2)

    一.什么是长连接 HTTP1.1规定了默认保持长连接(HTTP persistent connection ,也有翻译为持久连接),数据传输完成了保持TCP连接不断开(不发RST包.不四次握手),等待 ...

  5. Mac下配置Nginx负载均衡

    1.首先在Mac下安装Nginx(可参考我的另一篇随笔http://www.cnblogs.com/malcolmfeng/p/6896703.html). 2.安装Tomcat,下载后,解压,bin ...

  6. js继承之借用构造函数继承

    我的上一篇文章介绍了,原型链继承模式.但是单纯的原型链模式并不能很好地实现继承. 一.原型链的缺点 1.1 单纯的原型链继承最大的一个缺点,来自于原型中包含引用类型的值. 本来,我们没有通过原型链实现 ...

  7. VR全景智慧城市——商家的需求才是全景市场的核心竞争力

    消费者视角痛点:比如酒店消费行业,很多消费者在预订酒店过程中,都遇到过这样的场景:网上照片里酒店房间看着宽敞明亮,格调不凡,感觉非常喜欢,等真正推开房门插上房卡一看,却大失所望.在酒店行业,网上照片和 ...

  8. 模板C++ 03图论算法 2最短路之全源最短路(Floyd)

    3.2最短路之全源最短路(Floyd) 这个算法用于求所有点对的最短距离.比调用n次SPFA的优点在于代码简单,时间复杂度为O(n^3).[无法计算含有负环的图] 依次扫描每一点(k),并以该点作为中 ...

  9. 基于谱聚类的三维网格分割算法(Spectral Clustering)

    谱聚类(Spectral Clustering)是一种广泛使用的数据聚类算法,[Liu et al. 2004]基于谱聚类算法首次提出了一种三维网格分割方法.该方法首先构建一个相似矩阵用于记录网格上相 ...

  10. nodejs零基础详细教程1:安装+基础概念

    第一章 建议学习时间2小时  课程共10章 学习方式:详细阅读,并手动实现相关代码 学习目标:此教程将教会大家 安装Node.搭建服务器.express.mysql.mongodb.编写后台业务逻辑. ...