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.pswp.cn/news/373291.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/373291.shtml
英文地址,請注明出處:http://en.pswp.cn/news/373291.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

flex java 開發環境搭建_Flex+JAVA+BlazeDS開發環境配置(Java工程和Flex工程獨立)

FlexJAVABlazeDS開發環境配置(Java工程和Flex工程獨立)2019年12月07日閱讀數&#xff1a;7這篇文章主要向大家介紹FlexJAVABlazeDS開發環境配置(Java工程和Flex工程獨立),主要內容包括基礎應用、實用技巧、原理機制等方面&#xff0c;希望對大家有所幫助。[url]http://blog.csd…

1251 括號(遞歸小練)

1251 括號 時間限制: 1 s空間限制: 128000 KB題目等級 : 黃金 Gold題目描述 Description計算乘法時&#xff0c;我們可以添加括號&#xff0c;來改變相乘的順序&#xff0c;比如計算              X1, X2, X3, X4, …, XN的積&#xff0c;可以 (X1(X2(X3(X4(...(XN-1…

zabbix_agentd.conf配置文件詳解

Aliaskey的別名&#xff0c;例如 Aliasttlsa.userid:vfs.file.regexp[/etc/passwd,^ttlsa:.:([0-9]),,,,\1]&#xff0c; 或者ttlsa的用戶ID。你可以使用key&#xff1a;vfs.file.regexp[/etc/passwd,^ttlsa:.: ([0-9]),,,,\1]&#xff0c;也可以使用ttlsa.userid。備注: 別名不…

在運行時修補Java

本文將重點介紹如何解決與第三方庫相關的問題 不能被規避 難以排除/繞過/替換 只需不提供錯誤修正 在這種情況下&#xff0c;解決問題仍然是一項艱巨的任務。 作為這種情況的誘因&#xff0c;請考慮對“哈希索引”數據結構的攻擊&#xff0c;例如java.util.Hashtable和java…

php return直接輸出,PHP中return用法詳細解讀

原標題&#xff1a;PHP中return用法詳細解讀在大部分編程語言中&#xff0c;return關鍵字可以將函數的執行結果返回&#xff0c;PHP中return的用法也大同小異&#xff0c;對初學者來說&#xff0c;掌握PHP中return的用法也是學習PHP的一個開始。首先&#xff0c;它的意思就是返…

并行執行,沒用到過,寫到這里免得搞忘

/// <summary>/// /// </summary>class Program{static void Main(string[] args){simultaneous();Console.ReadKey();}static void simultaneous(){//盡可能并行執行提供的每個操作Parallel.Invoke(() > ComplexMethod("1"),() > ComplexMethod(&…

UIViewController生命周期

UIViewController生命周期 UIViewController生命周期 posted on 2016-04-07 20:15 相而勿絕 閱讀(...) 評論(...) 編輯 收藏 轉載于:https://www.cnblogs.com/fmdxiangdui/p/5365249.html

Spring的REST分頁

這是有關使用Spring 3.1和Spring Security 3.1和基于Java的配置來建立安全的RESTful Web Service的系列文章的第七篇。 本文將重點介紹RESTful Web服務中的分頁實現 。 REST with Spring系列&#xff1a; 第1部分– 使用Spring 3.1和基于Java的配置引導Web應用程序 第2部分–…

眾籌源碼 php,助創cms眾籌源碼系統v1.0

什么是助創cms眾籌系統?使用“預約團購”的眾籌方式給自己的創意爭取大家的關注和支持&#xff0c;是近年來非常火熱的一種融資模式&#xff0c;助創cms眾籌系統可以10分鐘幫你打造一個和京東眾籌一樣的平臺&#xff0c;包含產品眾籌和公益眾籌兩個部分&#xff0c;可以直接拿…

Linq to SQL 的增刪改查操作

Linq&#xff0c;全稱Language Integrated Query&#xff0c;作為C#3.0新語法&#xff0c;是C#語言的一個擴展&#xff0c;可以將數據查詢直接集成到編程語言本身中。 Linq表達式和SQL語句差不多&#xff0c;說白了就是顛倒sql語法&#xff0c; from where select ...&#xff…

擴展您的JPA POJO

可擴展性是許多體系結構的重要特征。 它衡量是否容易&#xff08;或困難&#xff09; 它是在不影響現有核心系統功能的情況下添加或更改功能。 讓我們舉一個簡單的例子。 假設您的公司擁有一個核心產品來跟蹤體育俱樂部中的所有用戶。 在您的產品體系結構中&#xff0c;您有一個…

web框架--flask

flask介紹Flask是一個基于Python開發并且依賴jinja2模板和Werkzeug WSGI服務的一個微型框架&#xff0c;對于Werkzeug本質是Socket服務端&#xff0c;其用于接收http請求并對請求進行預處理&#xff0c;然后觸發Flask框架&#xff0c;開發人員基于Flask框架提供的功能對請求進行…

php spider shell,ScrapyShell使用

Scrapy ShellScrapy終端是一個交互終端&#xff0c;我們可以在未啟動spider的情況下嘗試及調試代碼&#xff0c;也可以用來測試XPath或CSS表達式&#xff0c;查看他們的工作方式&#xff0c;方便我們爬取的網頁中提取的數據。如果安裝了 IPython &#xff0c;Scrapy終端將使用 …

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;我只是…

Java小青蛙跳臺街,算法-青蛙跳臺階詳解

/*[跳臺階][題目]一只青蛙一次可以跳上1級臺階&#xff0c;也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法。[解析]與斐波那契數列的求解過程類似。典型的動態規劃問題。對于第 n 級臺階&#xff0c;我們可以從第 n-1 級臺階一步到達&#xff0c;也可以從第 n-2 級…

apache服務器配置Net的實踐

前置&#xff1a; 在xp系統中&#xff0c;打補丁之類或啥子操作引起或多或少的問題&#xff0c;最終導致iis不能使用&#xff1b; 不想裝系統...忍著... 最近突發事件導致&#xff0c;需要摸一下apache服務器處理&#xff0c;好吧&#xff0c;那就搜索下吧..... 目標&#xff1…

TestNG或JUnit

多年以來&#xff0c;無論何時使用Java代碼進行單元測試&#xff0c;我始終會回到TestNG。 每當我拿起TestNG時&#xff0c;人們都問我為什么要繼續使用TestNG&#xff0c;尤其是默認開發環境&#xff08;例如Eclipse或Maven&#xff09;提供的JUnit時。 繼續進行同樣的戰斗&am…

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…