java的oauth2.0_[转]Java的oauth2.0 服务端与客户端的实现

oauth原理简述

oauth本身不是技术,而是一项资源授权协议,重点是协议!Apache基金会提供了针对Java的oauth封装。我们做Java web项目想要实现oauth协议进行资源授权访问,直接使用该封装就可以。

71900b5919b9

image.png

整个开发流程简述一下:

1、 在客户端web项目中构造一个oauth的客户端请求对象(OAuthClientRequest),在此对象中携带客户端信息(clientId、accessTokenUrl、response_type、redirectUrl),将此信息放入http请求中,重定向到服务端。此步骤对应上图1

2、 在服务端web项目中接受第一步传过来的request,从中获取客户端信息,可以自行验证信息的可靠性。同时构造一个oauth的code授权许可对象(OAuthAuthorizationResponseBuilder),并在其中设置授权码code,将此对象传回客户端。此步骤对应上图2

3、 在在客户端web项目中接受第二步的请求request,从中获得code。同时构造一个oauth的客户端请求对象(OAuthClientRequest),此次在此对象中不仅要携带客户端信息(clientId、accessTokenUrl、clientSecret、GrantType、redirectUrl),还要携带接受到的code。再构造一个客户端请求工具对象(oAuthClient),这个工具封装了httpclient,用此对象将这些信息以post(一定要设置成post)的方式请求到服务端,目的是为了让服务端返回资源访问令牌。此步骤对应上图3。(另外oAuthClient请求服务端以后,会自行接受服务端的响应信息。

4、 在服务端web项目中接受第三步传过来的request,从中获取客户端信息和code,并自行验证。再按照自己项目的要求生成访问令牌(accesstoken),同时构造一个oauth响应对象(OAuthASResponse),携带生成的访问指令(accesstoken),返回给第三步中客户端的oAuthClient。oAuthClient接受响应之后获取accesstoken,此步骤对应上图4

5、 此时客户端web项目中已经有了从服务端返回过来的accesstoken,那么在客户端构造一个服务端资源请求对象(OAuthBearerClientRequest),在此对象中设置服务端资源请求URI,并携带上accesstoken。再构造一个客户端请求工具对象(oAuthClient),用此对象去服务端靠accesstoken换取资源。此步骤对应上图5

6、 在服务端web项目中接受第五步传过来的request,从中获取accesstoken并自行验证。之后就可以将客户端请求的资源返回给客户端了。

代码:

客户端:

一、pom依赖:

org.apache.oltu.oauth2

org.apache.oltu.oauth2.client

0.31

二、controller方法:

2.1 向服务端请求授权码code的controller方法:

@RequestMapping("/server")

@Controller

public class ServerController{

String clientId = null;

String clientSecret = null;

String accessTokenUrl = null;

String userInfoUrl = null;

String redirectUrl = null;

String response_type = null;

String code= null;

//提交申请code的请求

@RequestMapping("/requestServerCode")

public String requestServerFirst(HttpServletRequestrequest, HttpServletResponseresponse, RedirectAttributesattr) throws OAuthProblemException{

clientId = "clientId";

clientSecret = "clientSecret";

accessTokenUrl = "responseCode";

redirectUrl = "http://localhost:8081/oauthclient01/server/callbackCode";

response_type = "code";

OAuthClient oAuthClient =new OAuthClient(new URLConnectionClient());

String requestUrl = null;

try {

//构建oauthd的请求。设置请求服务地址(accessTokenUrl)、clientId、response_type、redirectUrl

OAuthClientRequest accessTokenRequest = OAuthClientRequest

.authorizationLocation(accessTokenUrl)

.setResponseType(response_type)

.setClientId(clientId)

.setRedirectURI(redirectUrl)

.buildQueryMessage();

requestUrl = accessTokenRequest.getLocationUri();

System.out.println(requestUrl);

} catch (OAuthSystemExceptione) {

e.printStackTrace();

}

return "redirect:http://localhost:8082/oauthserver/"+requestUrl ;

}

此段代码对应开发步骤1.其中accessTokenUrl是服务端返回code的controller方法映射地址。redirectUrl是告诉服务端,code要传回客户端的一个controller方法,该方法的映射地址就是redirectUrl。

2.2 向服务端请求资源访问令牌access token的controller方法:

//接受客户端返回的code,提交申请access token的请求

@RequestMapping("/callbackCode")

public Object toLogin(HttpServletRequestrequest)throws OAuthProblemException{

System.out.println("-----------客户端/callbackCode--------------------------------------------------------------------------------");

clientId = "clientId";

clientSecret = "clientSecret";

accessTokenUrl="http://localhost:8082/oauthserver/responseAccessToken";

userInfoUrl = "userInfoUrl";

redirectUrl = "http://localhost:8081/oauthclient01/server/accessToken";

HttpServletRequest httpRequest = (HttpServletRequest)request;

code = httpRequest.getParameter("code");

System.out.println(code);

OAuthClient oAuthClient =new OAuthClient(new URLConnectionClient());

try {

OAuthClientRequest accessTokenRequest = OAuthClientRequest

.tokenLocation(accessTokenUrl)

.setGrantType(GrantType.AUTHORIZATION_CODE)

.setClientId(clientId)

.setClientSecret(clientSecret)

.setCode(code)

.setRedirectURI(redirectUrl)

.buildQueryMessage();

//去服务端请求access token,并返回响应

OAuthAccessTokenResponse oAuthResponse =oAuthClient.accessToken(accessTokenRequest, OAuth.HttpMethod.POST);

//获取服务端返回过来的access token

String accessToken = oAuthResponse.getAccessToken();

//查看access token是否过期

Long expiresIn =oAuthResponse.getExpiresIn();

System.out.println("客户端/callbackCode方法的token:::"+accessToken);

System.out.println("-----------客户端/callbackCode--------------------------------------------------------------------------------");

return"redirect:http://localhost:8081/oauthclient01/server/accessToken?accessToken="+accessToken;

} catch (OAuthSystemExceptione) {

e.printStackTrace();

}

return null;

}

此方法对应开发步骤3的全部和步骤4的一半,也就是还包括接受服务端返回的access token。最后的redirect地址不是服务端的地址,只是将此token传进客户端的另一个方法,该方法就是最后的资源请求方法。

2.3 利用服务端给的token去请求服务端的资源的controller方法。这里说的资源就是服务端数据库中的user表的uname值的拼接字段。

//接受服务端传回来的access token,由此token去请求服务端的资源(用户信息等)

@RequestMapping("/accessToken")

public ModelAndView accessToken(StringaccessToken) {

System.out.println("---------客户端/accessToken----------------------------------------------------------------------------------");

userInfoUrl = "http://localhost:8082/oauthserver/userInfo";

System.out.println("accessToken");

OAuthClient oAuthClient =new OAuthClient(new URLConnectionClient());

try {

OAuthClientRequest userInfoRequest =new OAuthBearerClientRequest(userInfoUrl)

.setAccessToken(accessToken).buildQueryMessage();

OAuthResourceResponse resourceResponse =oAuthClient.resource(userInfoRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);

String username = resourceResponse.getBody();

System.out.println(username);

ModelAndView modelAndView =new ModelAndView("usernamePage");

modelAndView.addObject("username",username);

System.out.println("---------客户端/accessToken----------------------------------------------------------------------------------");

returnmodelAndView;

} catch (OAuthSystemExceptione) {

e.printStackTrace();

} catch (OAuthProblemExceptione) {

e.printStackTrace();

}

System.out.println("---------客户端/accessToken----------------------------------------------------------------------------------");

return null;

}

此方法对应开发步骤5的全部和步骤6的一半,也就是还包括接受服务端返回的资源信息。获取了资源信息之后,其余的开发就和平时的springmvc一毛一样了。

以上三个方法我全部封装在同一个ServerController类中。

服务端

三 pom依赖

org.apache.oltu.oauth2

org.apache.oltu.oauth2.authzserver

0.31

org.apache.oltu.oauth2

org.apache.oltu.oauth2.resourceserver

0.31

四 controller方法

4.1 向客户端返回授权码code的controller方法

@Controller

public class AuthorizeController{

@Autowired

private UserServiceuserService;

//向客户端返回授权许可码 code

@RequestMapping("/responseCode")

public Object toShowUser(Modelmodel, HttpServletRequestrequest){

System.out.println("----------服务端/responseCode--------------------------------------------------------------");

try {

//构建OAuth授权请求

OAuthAuthzRequest oauthRequest =new OAuthAuthzRequest(request);

/*oauthRequest.getClientId();

oauthRequest.getResponseType();

oauthRequest.getRedirectURI();

System.out.println(oauthRequest.getClientId());

System.out.println(oauthRequest.getResponseType());

System.out.println(oauthRequest.getRedirectURI());*/

if(oauthRequest.getClientId()!=null&&oauthRequest.getClientId()!="")

{

//设置授权码

String authorizationCode ="authorizationCode";

//利用oauth授权请求设置responseType,目前仅支持CODE,另外还有TOKEN

String responseType =oauthRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE);

//进行OAuth响应构建

OAuthASResponse.OAuthAuthorizationResponseBuilderbuilder =

OAuthASResponse.authorizationResponse(request, HttpServletResponse.SC_FOUND);

//设置授权码

builder.setCode(authorizationCode);

//得到到客户端重定向地址

String redirectURI =oauthRequest.getParam(OAuth.OAUTH_REDIRECT_URI);

//构建响应

final OAuthResponseresponse =builder.location(redirectURI).buildQueryMessage();

System.out.println("服务端/responseCode内,返回的回调路径:"+response.getLocationUri());

System.out.println("----------服务端/responseCode--------------------------------------------------------------");

String responceUri =response.getLocationUri();

//根据OAuthResponse返回ResponseEntity响应

HttpHeaders headers =new HttpHeaders();

try {

headers.setLocation(new URI(response.getLocationUri()));

} catch (URISyntaxExceptione) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return"redirect:"+responceUri;

}

} catch (OAuthSystemExceptione) {

e.printStackTrace();

} catch (OAuthProblemExceptione) {

e.printStackTrace();

}

System.out.println("----------服务端/responseCode--------------------------------------------------------------");

return null;

}

}

此段代码对应开发步骤2

4.2 向客户端返回资源访问令牌accesstoken的controller方法

@Controller

public class AccessTokenController {

//获取客户端的code码,向客户端返回access token

@RequestMapping(value="/responseAccessToken",method = RequestMethod.POST)

public HttpEntity token(HttpServletRequest request){

System.out.println("--------服务端/responseAccessToken-----------------------------------------------------------");

OAuthIssuer oauthIssuerImpl=null;

OAuthResponse response=null;

//构建OAuth请求

try {

OAuthTokenRequest oauthRequest =new OAuthTokenRequest(request);

String authCode =oauthRequest.getParam(OAuth.OAUTH_CODE);

String clientSecret = oauthRequest.getClientSecret();

if(clientSecret!=null||clientSecret!=""){

//生成Access Token

oauthIssuerImpl =new OAuthIssuerImpl(new MD5Generator());

final StringaccessToken =oauthIssuerImpl.accessToken();

System.out.println(accessToken);

System.out.println("--oooo---");

//生成OAuth响应

response = OAuthASResponse

.tokenResponse(HttpServletResponse.SC_OK)

.setAccessToken(accessToken)

.buildJSONMessage();

}

System.out.println("--------服务端/responseAccessToken-----------------------------------------------------------");

//根据OAuthResponse生成ResponseEntity

return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));

} catch (OAuthSystemExceptione) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (OAuthProblemExceptione) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println("--------服务端/responseAccessToken-----------------------------------------------------------");

return null;

}

}

此段代码对应开发步骤4的前面一半,即服务端验证code、生成token并给客户端

4.3 向客户端返回请求资源(username)的controller方法

@Controller

public class UserInfoController {

@Autowired

private UserServiceuserService;

@RequestMapping("/userInfo")

public HttpEntity userInfo(HttpServletRequest request)throws OAuthSystemException{

System.out.println("-----------服务端/userInfo-------------------------------------------------------------");

try {

//获取客户端传来的OAuth资源请求

OAuthAccessResourceRequest oauthRequest =new OAuthAccessResourceRequest(request, ParameterStyle.QUERY);

//获取Access Token

String accessToken =oauthRequest.getAccessToken();

System.out.println("accessToken");

//验证Access Token

/*if (accessToken==null||accessToken=="") {

// 如果不存在/过期了,返回未验证错误,需重新验证

OAuthResponse oauthResponse = OAuthRSResponse

.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)

.setError(OAuthError.ResourceResponse.INVALID_TOKEN)

.buildHeaderMessage();

HttpHeaders headers = new HttpHeaders();

headers.add(OAuth.HeaderType.WWW_AUTHENTICATE,

oauthResponse.getHeader(OAuth.HeaderType.WWW_AUTHENTICATE));

return new ResponseEntity(headers, HttpStatus.UNAUTHORIZED);

} */

//返回用户名

User user=userService.selectByPrimaryKey(1);

String username = accessToken+"---"+Math.random()+"----"+user.getUname();

System.out.println(username);

System.out.println("服务端/userInfo::::::ppp");

System.out.println("-----------服务端/userInfo----------------------------------------------------------");

return new ResponseEntity(username, HttpStatus.OK);

} catch (OAuthProblemExceptione) {

// TODO Auto-generated catch block

e.printStackTrace();

//检查是否设置了错误码

String errorCode =e.getError();

if (OAuthUtils.isEmpty(errorCode)) {

OAuthResponse oauthResponse = OAuthRSResponse

.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)

.buildHeaderMessage();

HttpHeaders headers =new HttpHeaders();

headers.add(OAuth.HeaderType.WWW_AUTHENTICATE,

oauthResponse.getHeader(OAuth.HeaderType.WWW_AUTHENTICATE));

return new ResponseEntity(headers, HttpStatus.UNAUTHORIZED);

}

OAuthResponse oauthResponse = OAuthRSResponse

.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)

.setError(e.getError())

.setErrorDescription(e.getDescription())

.setErrorUri(e.getUri())

.buildHeaderMessage();

HttpHeaders headers =new HttpHeaders();

headers.add(OAuth.HeaderType.WWW_AUTHENTICATE,

oauthResponse.getHeader(OAuth.HeaderType.WWW_AUTHENTICATE));

System.out.println("-----------服务端/userInfo------------------------------------------------------------------------------");

return new ResponseEntity(HttpStatus.BAD_REQUEST);

}

}

}

此代码对应开发步骤6的前一半。即服务端验证access token、并将资源信息给客户端

至此,整个Java集成oauth就完成了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/486851.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数学突破奖:告诉你一个真实的数学研究

文章来源:科学松鼠会科学是目前人类探知客观世界最好的方式。尽管投入科学不能一蹴而就地得到切实有用的成果,但长远来看却是技术发展最好的动力源。与技术开发不同,对科学的投入更像是公益活动,因为科学研究得到的成果属于全人类…

java 获取当前月份减1_java String 日期 转成 Date, 月份减1

ainiyanyan13142007-03-30 22:391 编写applet 程序的页面输出 红色的 "hello would !"2 请编写application 计算并 "12...2008"的结果3 找出两个字符串中所有共同的子字符串4 将碾转相除法求两个整数的最大公因数gcd(a,b)用递归方法实现.(1) 求两个整数a,b…

重磅!“全脑介观神经联接图谱”大科学计划中国工作组成立!

来源:上海科技9月27日下午,“全脑介观神经联接图谱”大科学计划启动前期工作座谈会在上海市召开,本次会议明确了该计划的推进路径,宣布了中国工作组的成立,并就该计划的具体实施思路和举措进行研讨。座谈会上&#xff…

算法训练 Pollution Solution(计算几何)

问题描述作为水污染管理部门的一名雇员,你需要监控那些被有意无意倒入河流、湖泊和海洋的污染物。你的其中一项工作就是估计污染物对不同的水生态系统(珊瑚礁、产卵地等等)造成的影响。你计算所使用的模型已经在图1中被说明。海岸线&#xff…

MEMS传感器前景光明,国内产业如何创新破局

来源:MEMS当前,在行业技术不断发展和成熟的加持下,物联网已经成为世界新一轮科技革命和产业变革的重要驱动力。顺应着万物互联时代的到来,作为物联网先行技术、感知层的代表——传感器的市场需求急剧攀升,所扮演的角色…

python3层装饰器_python三层装饰器python字符串,数值计算

Python是一种面向对象的语言,但它不像C一样把标准类都封装到库中,而是进行了进一步的封装,语言本身就集成一些类和函数,比如print,list,dict etc. 给编程带来很大的便捷Python 使用#进行单行注释&#xff0…

2.6 线程优先级

package 第二章.线程优先级;/** * Created by zzq on 2018/1/18. */public class 线程优先级 { public static class T1 extends Thread{ Override public void run() { System.out.println("-------"); } } public static…

清华大学教授:唐杰——深度分析:人工智能的下个十年

来源:图灵人工智能唐杰教授从人工智能发展的历史开始,深入分析人工智能近十年的发展,阐述了人工智能在感知方面取得的重要成果,尤其提到算法是这个感知时代最重要、最具代表性的内容。重点讲解了 BERT、ALBERT、MoCo2 等取得快速进…

java去掉mongodb日志_MongoDB日志文件过大的解决方法 清理

MongoDB日志文件过大的解决方法2016年05月09日 14:43:11 jjwen 阅读数 1261MongoDB的日志文件在设置 logappendtrue 的情况下,会不断向同一日志文件追加的,时间长了,自然变得非常大。解决如下:(特别注意:启动的时候必须…

Solr 访问 403 错误

把 Solr 基础环境搭建好后访问发现会出现 403 错误: 解决方法: 找到自己 Tomcat 目录下的 solr ,找到 ...\solr\WEB-INF\web.xml,然后把 169 - 183行注释,然后重启服务再次访问就 OK 啦。 访问成功界面: 转…

java数组的四个要素_Java零基础系列教程04Java数组

配套视频教程问题Java考试结束后,老师给张浩分配了一项任务,让他计算全班(30人)的平均分int stu1 95;int stu2 89;int stu3 79;int stu4 64;int stu5 76;int stu6 88;……avg (stu1stu2stu3stu4stu5…stu30)/30;数组数组是一个变量,存…

多页面webpack配置

工程结构如下 dev-serverconst config require(../config); const express require(express); const path require(path); const fs require(fs); // const faviconrequire(serve-favicon); const exec require(child_process).exec; process.env.NODE_ENV config.dev.e…

深度 | 量子计算技术的研究现状与未来

来源:本源量子导读1900年 Max Planck 提出“量子”概念,宣告了“量子”时代的诞生。科学家发现,微观粒子有着与宏观世界的物理客体完全不同的特性。宏观世界的物理客体,要么是粒子,要么是波动,它们遵从经典…

exsist什么意思_exist什么意思_通达信EXIST什么意思

matlab中的exist是什么意思exist用来判断变量或函数是否存在: exist Check if variables or functions are defined.exist(A) returns:0 if A does not exist1 if A is a variable in the workspace2 if A is an M-file on MATLABs search path. It also returns …

拥有“上帝视角”是怎样的体验?高分多模卫星首批影像成果发布

本文转载自“中国的航天”,原标题《拥有“上帝视角”是怎样的体验?高分多模卫星首批影像成果发布》,作者 | 杨璐9月29日,国家航天局发布了高分辨率多模综合成像卫星(以下简称“高分多模卫星”)首批20余幅亚…

1.2 - 列表练习题

1 1.创建列表2 >>> names [old_driver, rain, jack, shanshan, peiqi, black_girl]3 >>> names4 [old_driver, rain, jack, shanshan, peiqi, black_girl] 5 6 2.插入alex7 >>> names.insert(-1,alex)8 >>> names9 [old_driver, rain, ja…

java 工程ssl配置_HTTPS_SSL配置的步骤以及原理说明

1、单向认证,就是传输的数据加密过了,但是不会校验客户端的来源2、双向认证,如果客户端浏览器没有导入客户端证书,是访问不了web系统的,找不到地址,想要用系统的人没有证书就访问不了系统HTTPS概念方法/步骤…

我们人类与人工智能技术究竟是怎样的关系?

图片来自pixabay.com来源:赛先生撰文 | 爱德华阿什福德李(加州大学伯克利分校教授)责编 | 李珊珊摘要:数字技术正在和人类文明协同进化。我们依赖技术而生存,技术也依赖我们,这种合作共生的趋势越来越明显。…

Js拼接嵌套php代码,分享一个js文件中嵌套php会出错的问题

前提&#xff1a;使用ThinkPHP。后台传一个变量到html页面&#xff1a;$this->assign("variable", $variable);问题&#xff1a;在html页面中嵌套js代码&#xff0c;在js的代码中输出这个变量&#xff1a;var variable <?php echo $variable;?>;alert(va…

textarea标签内的文字无缘故居中解决原因

<textarea>内容内容</textarea>浏览器会解析为<textarea><br> 内容内容</textarea>可见在写<textarea>时一定要写成<textarea>内容内容</textarea> 必须写成一行&#xff01;转载于:https://www.cnblogs.com/zhaomeizi/p/…