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,一经查实,立即删除!

相关文章

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

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

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

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

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

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

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

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

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

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

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余幅亚…

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

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

中国工程院院士陈左宁详述:人工智能模型和算法的七大发展趋势

来源:C114通信网在近日举行的“第十六届CCF全过高性能计算学术年会”上,中国工程院副院长、中国科协副主席、中国工程院院士陈左宁发表了题为《人工智能进展对算力需求分析》的演讲。在演讲中,她阐述了人工智能模型和算法的七大发展趋势。陈左…

量子计算技术的研究现状与趋势

来源:《中国科学》 2020年 第50卷 第9期作者:郭光灿导读:1900年 Max Planck 提出“量子”概念,宣告了“量子”时代的诞生。科学家发现,微观粒子有着与宏观世界的物理客体完全不同的特性。宏观世界的物理客体&#xf…

Java毕业设计——springboot+vue电影院会员管理系统

1,项目背景 随着互联网时代的到来,同时计算机网络技术高速发展,网络管理运用也变得越来越广泛。因此,建立一个B/S结构的电影院会员管理系统;电影院会员管理系统的管理工作系统化、规范化,也会提高影院形象…

idea创建maven web项目

创建maven web项目 1:首先打开idea,点击“create new project“,在左边一栏找到maven,右边把“create from archetype“钩上,根据模版来创建项目, 注意在选择模版的时候一定要选择org.apache.maven.archety…

世界一流大学观察报告:斯坦福大学何以后来居上?

斯坦福大学(Stanford University)本文转自 管理学季刊 公众号文|石毓智,斯坦福大学博士、新加坡国立大学终身教职只有短短120年历史的斯坦福大学,已有近30人获得诺奖,不要说世界上其他大学难以匹敌,就是拿国家来比,能超…

PowerShell(PHPStorm terminal with PowerShell)运行git log中文乱码

解决方案: 1)以管理员身份运行PowerShell 2)新建一个针对PowerShell的Pofile文件 New-Item -Path $Profile -ItemType file -Force3)用记事本打开这个文件 notepad $Profile4)然后输入并保存退出 $env:LC_ALLC.UTF-85&…

机器学习研究者必知的八个神经网络架构

本文转自计算机视觉研究院本文简述了机器学习核心结构的历史发展,并总结了研究者需要熟知的 8 个神经网络架构。我们为什么需要「机器学习」?机器学习对于那些我们直接编程太过复杂的任务来说是必需的。有些任务很复杂,以至于人类不可能解决任…

php伪静态失败,php伪静态后html不能访问怎么办

php伪静态后html不能访问的解决办法:首先判断文件是否存在;然后设置存在则不rewirte,不存在且符合规则才rewrite;最后修改htaccess文件即可。具体问题:PHP伪静态后不能访问纯html文件.htaccess文件RewriteEngine onRew…