OAuth与Spring Security

摘自Wikipedia: OAuth开放式身份验证 )是一种开放式身份验证标准。 它允许用户与其他站点共享存储在一个站点上的私有资源(例如照片,视频,联系人列表),而不必发出其凭据(通常是用户名和密码)。

有很多关于客户端的 OAuth的帖子,例如如何连接到Twitter或Facebook之类的服务提供商,但是关于OAuth的帖子却很少,但是来自服务器端的帖子,更具体地讲,如何使用OAuth实施身份验证机制来保护用户资源,而不用于访问它们( 客户端部分 )。

在本文中,我将讨论如何使用Spring SecuritySpring Security OAuth )保护您的资源。 该示例非常简单,足以了解实现OAuth服务提供商的基础知识。

我发现这篇文章通过一个简单的示例说明了OAuth是什么以及它如何工作。 我认为这是使用OAuth的良好起点http://hueniverse.com/2007/10/beginners-guide-to-oauth-part-ii-protocol-workflow/

现在是时候开始编写我们的服务提供商了。 首先,我将解释我们的服务提供商将提供什么。

想象您正在开发一个网站(称为CV ),用户可以在该网站上注册,然后可以上传自己的简历 。 现在,我们将把这个网站转换为服务提供商,在其中OAuth将用于保护资源(注册用户的简历)。 再次想象一下,有些公司已经与简历人员达成协议,当他们发布职位空缺时,用户将可以直接从简历站点上载课程到人力资源部门,而无需通过电子邮件发送或从文档中复制粘贴。 如您所见,这里是OAuth开始管理CV网站和Company RH网站之间的安全性的地方。

总而言之,我们有一个具有受保护的资源(文档本身)的履历服务提供者CV )。 消费者是向用户提供直接从简历中获取其简历的可能性的公司。 因此,当用户访问公司职位空缺(在我们的示例中为fooCompany )并想要申请职位时,他只需要授权FooCompany “职位空缺”网站就可以从CV网站下载其简历

因为我们将使用Spring Security OAuth认证,首先我们要配置Spring Security 用SpringMVC进入CV应用。 这里没什么特别的:

web.xml文件中,我们定义了安全过滤器

<filter><filter-name>springSecurityFilterChain</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter><filter-mapping><filter-name>springSecurityFilterChain</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

root-context.xml中,我们定义了受保护的资源和身份验证管理器。 在这种情况下,使用内存中的方法:

<http auto-config='true'><intercept-url pattern="/**" access="ROLE_USER" />
</http><authentication-manager><authentication-provider><user-service><user name="leonard" password="nimoy" authorities="ROLE_USER" /></user-service></authentication-provider>
</authentication-manager>

下一步,创建一个Spring控制器 ,该控制器返回已登录用户的履历

@RequestMapping(value="/cvs", method=RequestMethod.GET)
@ResponseBody
public String loadCV() {StringBuilder cv = new StringBuilder();cv.append("Curriculum Vitae -- Name: ").append(getUserName()).append(" Experience: Java, Spring Security, ...");return cv.toString();
}private String getUserName() {Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();String username;if (principal instanceof UserDetails) {username = ((UserDetails)principal).getUsername();} else {username = principal.toString();}return username;
}

该控制器直接返回String,而不是ModelView对象。 该字符串直接作为HttpServletResponse发送。

现在,我们有一个简单的网站,可以返回已登录用户的简历 。 如果您尝试访问/ cvs资源,如果您未通过身份验证, Spring Security将显示一个登录页面,并且如果您已经登录,则将返回您的工作经验。 与使用Spring Security的任何其他网站一样工作

下一步是修改此项目,以允许外部站点可以使用OAuth 2身份验证协议访问受保护的资源。

root-context.xml中:

<beans:bean id="tokenServices"class="org.springframework.security.oauth2.provider.token.InMemoryOAuth2ProviderTokenServices"><beans:property name="supportRefreshToken" value="true" />
</beans:bean><oauth:provider client-details-service-ref="clientDetails"token-services-ref="tokenServices"><oauth:verification-code user-approval-page="/oauth/confirm_access" />
</oauth:provider><oauth:client-details-service id="clientDetails"><oauth:client clientId="foo" authorizedGrantTypes="authorization_code" />
</oauth:client-details-service>

第一个bean是具有id tokenServices的OAuth2ProviderTokenServices接口实现。 OAuth2ProviderTokenServices接口定义了管理OAuth 2.0令牌所需的操作。 这些令牌应被存储,以供后续访问令牌引用。 对于此示例,InMemory存储就足够了。

下一个bean是<oauth:provider>。 此标记用于配置OAuth 2.0提供程序机制。 并且在这种情况下,配置了三个参数。 第一个是对定义客户详细信息服务的Bean的引用,将在下一段中进行解释。 第二个是在前面的段落中说明的用于提供令牌的令牌服务,最后一个是将为授权令牌提供服务的URL。 这是通常的Authorize / Denny页面,服务提供商在该页面上询问用户是否允许消费者(在我们的情况下为fooCompany )访问受保护的资源(其履历表 )。

最后一个bean是<oauth:client-details-service>。 在此标签中,您可以定义您授权哪些客户端使用先前的身份验证来访问受保护的资源。 在这种情况下,由于CV公司已与foo公司达成协议,他们可以连接到其Curitaulum Vitae Service,因此使用id foo定义了一个客户端。

现在,我们使用OAuth配置了应用程序。 最后一步是创建一个控制器,用于接收来自/ oauth / confirm_access URL的请求。

private ClientAuthenticationCache authenticationCache = new DefaultClientAuthenticationCache();
private ClientDetailsService clientDetailsService;@RequestMapping(value="/oauth/confirm_access")
public ModelAndView accessConfirmation(HttpServletRequest request, HttpServletResponse response) {ClientAuthenticationToken clientAuth = getAuthenticationCache().getAuthentication(request, response);if (clientAuth == null) {throw new IllegalStateException("No client authentication request to authorize.");}ClientDetails client = getClientDetailsService().loadClientByClientId(clientAuth.getClientId());TreeMap<String, Object> model = new TreeMap<String, Object>();model.put("auth_request", clientAuth);model.put("client", client);return new ModelAndView("access_confirmation", model);
}

该控制器返回带有客户信息的ModelAndView对象,应显示哪个页面以授予对受保护资源的权限。 这个JSP页面称为access_confirmation.jsp ,最重要的部分是:

<div id="content"><% if (session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION) != null && !(session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION) instanceof UnapprovedClientAuthenticationException)) { %><div class="error"><p>Access could not be granted. (<%= ((AuthenticationException) session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION)).getMessage() %>)</p></div><% } %><c:remove scope="session" var="SPRING_SECURITY_LAST_EXCEPTION"/><authz:authorize ifAllGranted="ROLE_USER"><h2>Please Confirm</h2><p>You hereby authorize <c:out value="${client.clientId}"/> to access your protected resources.</p><form id="confirmationForm" name="confirmationForm" action="<%=request.getContextPath() + VerificationCodeFilter.DEFAULT_PROCESSING_URL%>" method="post"><input name="<%=BasicUserApprovalFilter.DEFAULT_APPROVAL_REQUEST_PARAMETER%>" value="<%=BasicUserApprovalFilter.DEFAULT_APPROVAL_PARAMETER_VALUE%>" type="hidden"/><label><input name="authorize" value="Authorize" type="submit"/></label></form><form id="denialForm" name="denialForm" action="<%=request.getContextPath() + VerificationCodeFilter.DEFAULT_PROCESSING_URL%>" method="post"><input name="<%=BasicUserApprovalFilter.DEFAULT_APPROVAL_REQUEST_PARAMETER%>" value="not_<%=BasicUserApprovalFilter.DEFAULT_APPROVAL_PARAMETER_VALUE%>" type="hidden"/><label><input name="deny" value="Deny" type="submit"/></label></form></authz:authorize></div>

如您所见, Spring Security OAuth提供了用于创建确认表单和拒绝表单的帮助程序类。 提交结果后,将调用URL / cv / oauth / user / authorize (内部管理), OAuth会根据用户选择的选项来决定是否将受保护的资源(由loadCV ()方法返回的字符串)返回给调用者。

这就是使用Spring Security OAuth创建OAuth 2系统的全部内容。 但是我想您想知道如何对其进行测试,因此以同样的价格,我还将解释如何使用Spring Security OAuth编写客户端部分(Consumer)。

客户端应用程序(称为fooCompany )也是具有Spring SecuritySpringMVC Web应用程序。

Spring Security部分在这里将被忽略。

客户端应用程序包含一个主页( home.jsp ),该主页具有指向Spring Controller的链接,该链接将负责从CV站点下载Curriculum Vitae ,并将内容重定向到视图( show.jsp )。

@RequestMapping(value="/cv")
public ModelAndView getCV() {String cv = cvService.getCVContent();Map<String, String> params = new HashMap<String, String>();params.put("cv", cv);ModelAndView modelAndView = new ModelAndView("show", params);return modelAndView;}

如您所见,它是一个简单的Controller,它调用了Curitaulum Vitae服务。 此服务将负责连接到简历网站,并下载所需的简历 。 当然,它也处理OAuth通信协议。

服务外观:

public String getCVContent() {byte[] content = (getCvRestTemplate().getForObject(URI.create(cvURL), byte[].class));return new String(content);
}

建议的访问这些资源的方法是使用Rest。 为此, Spring Security OAuth提供了RestTemplate的扩展,用于处理OAuth协议。 此类( OAuth2RestTemplate )管理与所需资源的连接,还管理令牌, OAuth授权协议等。

OAuth2RestTemplate被注入到CVService中,并被配置到root-context.xml中:

<oauth:client token-services-ref="oauth2TokenServices" /><beans:bean id="oauth2TokenServices"class="org.springframework.security.oauth2.consumer.token.InMemoryOAuth2ClientTokenServices" /><oauth:resource id="cv" type="authorization_code"clientId="foo" accessTokenUri="http://localhost:8080/cv/oauth/authorize"userAuthorizationUri="http://localhost:8080/cv/oauth/user/authorize" /><beans:bean id="cvService" class="org.springsource.oauth.CVServiceImpl"><beans:property name="cvURL" value="http://localhost:8080/cv/cvs"></beans:property><beans:property name="cvRestTemplate"><beans:bean class="org.springframework.security.oauth2.consumer.OAuth2RestTemplate"><beans:constructor-arg ref="cv"/></beans:bean>
</beans:property>
<beans:property name="tokenServices" ref="oauth2TokenServices"></beans:property>
</beans:bean>

看到OAuth2RestTemplate是使用OAuth资源创建的,其中包含有关授权访问受保护资源的连接位置的所有信息,并且在本例中是CV网站,请参见我们引用的是外部网站,尽管在此示例中,我们使用的是localhost。 还设置了服务提供者URL(http:// localhost:8080 / cvs / cv),因此RestTemplate可以建立与内容提供者的连接,并在授权过程成功结束的情况下,检索请求的信息。

<oauth:resource>定义OAuth资源,在这种情况下,定义为客户端的名称(请记住,此值是在服务器端客户端详细信息标签中配置的,用于授予对OAuth协议的访问权限)。 还定义了userAuthorizationUri 。 这是URI到用户是否曾经需要授权访问的资源(这是Spring Security中的OAuth管理内部URI)的用户将被重定向。 最后是accessTokenUri ,它是提供访问令牌(也是内部URI)的URI OAuth提供者端点。

使用Spring Security OAuth创建使用者也很简单。

现在,我将解释当用户希望授予foo公司以获取其履历的访问权时发生的事件的顺序。

首先,用户连接到foo网站,然后单击发布履历链接。 然后调用控制器的getCV方法。 此方法调用cvService ,同时使用OAuth2RestTemplate创建与资源URI(CV)的 连接 。 这个类作为一个黑盒子 ,从客户端,你不知道到底是什么这个类会做的,但它返回你的简历存储在简历的网站。 可以想象,该类管理与OAuth有关的所有工作流程,例如管理令牌,执行所需的URL重定向以获取权限等……并且,如果所有步骤都成功执行,则CV站点中存储的Curitaulum Vitae将发送到foo公司站点。

这就是所有允许您的网站使用OAuth2授权协议充当服务提供商的步骤。 感谢Spring Security的人们,一开始您可能会想起来容易得多。

希望你觉得它有用。

下载ServerSide(CV)
下载ClientSide(fooCompany)

参考:来自我们JCG合作伙伴的 带有Spring Security的OAuth   在一个罐子统治他们所有博客的亚历克斯·索托。


翻译自: https://www.javacodegeeks.com/2012/02/oauth-with-spring-security.html

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

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

相关文章

UIViewController生命周期

UIViewController生命周期 UIViewController生命周期 posted on 2016-04-07 20:15 相而勿绝 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/fmdxiangdui/p/5365249.html

众筹源码 php,助创cms众筹源码系统v1.0

什么是助创cms众筹系统?使用“预约团购”的众筹方式给自己的创意争取大家的关注和支持&#xff0c;是近年来非常火热的一种融资模式&#xff0c;助创cms众筹系统可以10分钟帮你打造一个和京东众筹一样的平台&#xff0c;包含产品众筹和公益众筹两个部分&#xff0c;可以直接拿…

69 个经典 Spring 面试题和答案

Spring 概述 什么是spring?Spring 是个java企业级应用的开源开发框架。Spring主要用来开发Java应用&#xff0c;但是有些扩展是针对构建J2EE平台的web应用。Spring 框架目标是简化Java企业级应用开发&#xff0c;并通过POJO为基础的编程模型促进良好的编程习惯。使用Spring框架…

高性能MySql

1、索引是对DB优化最有效的方式 varchar(10)定义的是字符的个数&#xff0c;如果是utf-8的话&#xff0c;最大是3X10个字节 二、索引类型 1、MySql的索引是在存储引擎层实现的&#xff0c;各个存储引擎的的索引方式也是不同的 2、B-Tree索引 MyISAM索引通过数据的物理位置引用被…

Java Swing井字游戏

大家好&#xff01; 哇&#xff0c;自从我在这里发布了东西以来已经有一段时间了&#xff01; 我必须说我真的很想写东西&#xff0c;而且我保证我不会再陷入“作家的障碍”。 希望 ..最近两个月发生了很多事情&#xff0c;我有很多话要说。 但是在这篇文章中&#xff0c;我只是…

event php,PHP event 事件机制

/** PHP 事件机制*/class baseClass{private $_e;public function __set($name,$value){if( strncasecmp($name,"on",2) 0 ){if(!isset($this->_e[$name]))$this->_e[$name] array();return array_push($this->_e[$name] , $value);}}public function __g…

Android JNI编程(五)——C语言的静态内存分配、动态内存分配、动态创建数组...

版权声明&#xff1a;本文出自阿钟的博客&#xff0c;转载请注明出处:http://blog.csdn.net/a_zhon/。 目录(?)[] 一&#xff1a;什么是静态内存什么又是动态内存呢&#xff1f; 静态内存&#xff1a;是指在程序开始运行时由编译器分配的内存&#xff0c;它的分配是在程序开始…

配置MyBatis 3

MyBatis是一个非常流行且也是最有效的SQL映射框架。 MyBatis可用于Java和.net语言。 MyBatis并不是Hibernate的真正替代品&#xff0c;但是我们可以使用该框架来减少MyBatis提供的高效和高性能的数据库相关代码。 本教程将向您展示使用数据库配置MyBatis 3的步骤。 MyBatis 3支…

java中datetime类型转换,Java中日期格式和其他类型转换详解

涉及的核心类&#xff1a;Date类、SimpleDateFormat类、Calendar类一、Date型与long型Date型转换为long型Date date new Date();//取得当前时间Date类型long date2long date.getTime();//Date转longlong型转换为Date型long cur System.currentTimeMills();//取得当前时间lon…

GWT MVP变得简单

GWT Model-View-Presenter是用于大规模应用程序开发的设计模式。 它源于MVC&#xff0c;它在视图和逻辑之间进行划分&#xff0c;并有助于创建结构良好&#xff0c;易于测试的代码。 为了帮助像我这样的懒惰开发人员&#xff0c;我研究了如何减少使用声明式UI时要编写的类和接口…

今年计划要看的书全部备齐

上个月购买的书《今年计划看的书其中几本》 http://www.cnblogs.com/insus/p/5325513.html 昨天购买的书回来了&#xff0c;今年计划要看的书全部备齐。《MongoDB》&#xff0c;《深入理解Bootstarp》和《ASP.NETSignalR编程实践》…… 转载于:https://www.cnblogs.com/in…

图形教程

众所周知&#xff0c;我们可以借助Java库制作游戏&#xff0c;这些库为我们提供制作游戏所需的图形。 因此&#xff0c;今天我将开始一个关于Java图形的非常新的部分。 我之前曾发表过有关如何制作所得税计算器的文章 。 首先要满足一些先决条件&#xff1a; -您应该对Java语法…

向导设计模式

我们都喜欢巫师……。 &#xff08;我的意思是软件向导&#xff09;。 我们总是很高兴跳上那些“下一步”按钮&#xff0c;就像我们在我们的时髦的小鸡上跳舞一样。 因此&#xff0c;今天我们将您心爱的向导带入您的编码经验中。 让我们跳入一个例子。 假设您要设计一个Conserv…

Flex 布局教程:语法篇

网页布局&#xff08;layout&#xff09;是CSS的一个重点应用。 布局的传统解决方案&#xff0c;基于盒状模型&#xff0c;依赖 display属性 position属性 float属性。它对于那些特殊布局非常不方便&#xff0c;比如&#xff0c;垂直居中就不容易实现。 2009年&#xff0c;W3…

JavaFX 2中的PopupMenu

创建弹出菜单 要在JavaFX中创建Popupmenu&#xff0c;可以使用ContextMenu类。 您向其中添加MenuItems&#xff0c;也可以使用SeparatorMenuItem创建可视分隔符。 在下面的示例中&#xff0c;我选择子类ContextMenu并将MenuItems添加到其构造函数中。 public class Animatio…

matlab中CH指标聚类评价指标,MATLAB聚类有效性评价指标(外部)

MATLAB聚类有效性评价指标(外部)作者&#xff1a;凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/更多内容&#xff0c;请看标签&#xff1a;MATLAB、聚类前提&#xff1a;数据的真实标签已知&#xff01;1. 归一化互信息(Normalized Mutual information)定义程序functio…

php-cgi cpu很高,php-cgi占用cpu资源过高的解决方法

转的网上的&#xff0c;不过对PHP-CGI菜鸟的人&#xff0c;还是有点帮助的。1. 一些php的扩展与php版本兼容存在问题&#xff0c;实践证明 eAccelerater与某些php版本兼容存在问题&#xff0c;具体表现时启动php-cgi进程后&#xff0c;运行10多分钟&#xff0c;奇慢无比&#x…

多表之间关联查询

内连接 jion on 自连接 本表进行内连接的查询形式 外链接&#xff1a; 左链接 写法&#xff1a;select 字段 from 表1 t left join 表2 s on t.字段1 s.字段1 where 条件 或者 作用&#xff1a;保证左边的表的数据全部显示&#xff0c;包括空的 右链接 写法 &#xff1a;sele…

Java 7:WatchService

在Java 7的所有新功能中&#xff0c;更有趣的是WatchService&#xff0c;它增加了监视目录更改的功能。 WatchService直接映射到本机文件事件通知机制&#xff08;如果有&#xff09;。 如果本机事件通知机制不可用&#xff0c;则默认实现将使用轮询。 结果&#xff0c;响应性&…

做一件事情的3个关键指标:兴趣、能力和回报

最近突然有了一点新的感悟&#xff0c;在原有的认识基础之上。关于找工作&#xff0c;大家说的最多的&#xff0c;根据自己的“兴趣”和“能力”。我觉得这是不够的&#xff0c;还应该加上一个“回报”。兴趣&#xff1a;对一件事有没有愿望去尝试&#xff0c;侧重“好奇心”。…