使用OAuth2令牌的安全REST服务
1.簡介
在本教程中,我們將介紹如何將Spring Security與OAuth結合使用以保護REST服務。 在演示應用程序中,可以使用路徑模式( / api / ** )訪問服務器上受保護的REST資源,以便基于該路徑的請求URL映射到不同的控制器方法。 這意味著 -
- 路徑中沒有' / api '的任何REST請求URL都將保持無效 ,因為這些URL與任何控制器映射都不匹配。
- 完成所需的OAuth2配置后,任何不帶令牌作為參數的REST請求URL都將是未授權的 。
我們配置的另一個路徑模式( / oauth / token )將幫助已配置的授權服務器生成訪問令牌。 請注意,我們將在此演示應用程序中使用“ 密碼授予類型” 。
在繼續實施之前,讓我們回顧一下與該授予類型有關的事件。
2.資源所有者密碼憑證授予類型
- 在受信任的應用程序之間使用。
- 用戶(資源所有者)直接與客戶端應用程序共享憑據,客戶端應用程序在成功驗證用戶憑據并進一步授權用戶訪問服務器上的有限資源后,請求授權服務器返回訪問令牌。
有用的鏈接
- 了解有關其他授權授予類型的更多信息
- 了解OAuth2令牌認證
3.實施
確保將所需的pom條目正確添加到pom.xml文件中。
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.springframework.samples.service.service</groupId><artifactId>SecureRESTWithOAuth</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><!-- Spring dependencies --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>4.2.1.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>4.2.1.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>4.2.1.RELEASE</version></dependency><!-- Jackson JSON Processor --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.4.1</version></dependency><!-- Spring Security Dependencies --><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-core</artifactId><version>3.2.3.RELEASE</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-web</artifactId><version>3.2.3.RELEASE</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-config</artifactId><version>3.2.3.RELEASE</version></dependency><dependency><groupId>org.springframework.security.oauth</groupId><artifactId>spring-security-oauth2</artifactId><version>1.0.0.RELEASE</version></dependency></dependencies> </project>web.xml
更新web.xml文件以加載上下文文件并配置Spring Security過濾器,該過濾器將在處理請求之前重定向身份驗證和授權請求。
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"id="WebApp_ID" version="2.5"><display-name>SecureRESTWithOAuth</display-name><servlet><servlet-name>mvc-dispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>mvc-dispatcher</servlet-name><url-pattern>/*</url-pattern></servlet-mapping><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- Loads context files --><context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/mvc-dispatcher-servlet.xml,/WEB-INF/spring-security.xml</param-value></context-param><!-- Spring Security --><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></web-app>mvc-dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"><context:component-scan base-package="com.jcombat.controller" /><mvc:annotation-driven /></beans>由于我們將使用admin JSP文件,因此我們已經為其配置了相應的視圖解析器。
現在,讓我們在其上下文文件中配置Spring Security OAuth。
spring-security.xml
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"xmlns:context="http://www.springframework.org/schema/context"xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd "><!-- Default url to get a token from OAuth --><http pattern="/oauth/token" create-session="stateless"authentication-manager-ref="clientAuthenticationManager"xmlns="http://www.springframework.org/schema/security"><intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" /><anonymous enabled="false" /><http-basic entry-point-ref="clientAuthenticationEntryPoint" /><custom-filter ref="clientCredentialsTokenEndpointFilter"after="BASIC_AUTH_FILTER" /><access-denied-handler ref="oauthAccessDeniedHandler" /></http><!-- URLs should be protected and what roles have access to them --><!-- Can define more patterns based on the protected resources hosted on the server --><http pattern="/api/**" create-session="never"entry-point-ref="oauthAuthenticationEntryPoint"access-decision-manager-ref="accessDecisionManager"xmlns="http://www.springframework.org/schema/security"><anonymous enabled="false" /><intercept-url pattern="/api/**" access="ROLE_APP" /><!-- Protect oauth clients with resource ids --><custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /><access-denied-handler ref="oauthAccessDeniedHandler" /></http><bean id="oauthAuthenticationEntryPoint"class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"><property name="realmName" value="demo/client" /></bean><bean id="clientAuthenticationEntryPoint"class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"><property name="realmName" value="demo/client" /><property name="typeName" value="Basic" /></bean><bean id="oauthAccessDeniedHandler"class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" /><bean id="clientCredentialsTokenEndpointFilter"class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter"><property name="authenticationManager" ref="clientAuthenticationManager" /></bean><bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"xmlns="http://www.springframework.org/schema/beans"><constructor-arg><list><bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" /><bean class="org.springframework.security.access.vote.RoleVoter" /><bean class="org.springframework.security.access.vote.AuthenticatedVoter" /></list></constructor-arg></bean><authentication-manager id="clientAuthenticationManager"xmlns="http://www.springframework.org/schema/security"><authentication-provider user-service-ref="clientDetailsUserService" /></authentication-manager><!-- This is simple authentication manager, with a hard-coded username/password combination. We can replace this with a user defined service to fetch user credentials from DB instead --><authentication-manager alias="authenticationManager"xmlns="http://www.springframework.org/schema/security"><authentication-provider><user-service><user name="admin" password="123" authorities="ROLE_APP" /></user-service></authentication-provider></authentication-manager><bean id="clientDetailsUserService"class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService"><constructor-arg ref="clientDetails" /></bean><!-- This defines the token store. We have currently used in-memory token store but we can instead use a user defined one --><bean id="tokenStore"class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" /><!-- If need to store tokens in DB <bean id="tokenStore"class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore"><constructor-arg ref="jdbcTemplate" /></bean> --><!-- This is where we defined token based configurations, token validity and other things --><bean id="tokenServices"class="org.springframework.security.oauth2.provider.token.DefaultTokenServices"><property name="tokenStore" ref="tokenStore" /><property name="supportRefreshToken" value="true" /><property name="accessTokenValiditySeconds" value="120" /><property name="clientDetailsService" ref="clientDetails" /></bean><bean id="userApprovalHandler"class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler"><property name="tokenServices" ref="tokenServices" /></bean><!-- The server issuing access tokens to the client after successfully authenticating the resource owner and obtaining authorization --><oauth:authorization-serverclient-details-service-ref="clientDetails" token-services-ref="tokenServices"user-approval-handler-ref="userApprovalHandler"><oauth:authorization-code /><oauth:implicit /><oauth:refresh-token /><oauth:client-credentials /><oauth:password /></oauth:authorization-server><!-- Define protected resources hosted by the resource server --><oauth:resource-server id="resourceServerFilter"resource-id="adminProfile" token-services-ref="tokenServices" /><!-- OAuth clients allowed to access the protected resources, can be something like facebook, google if we are sharing any resource with them --><oauth:client-details-service id="clientDetails"><oauth:client client-id="fbApp"authorized-grant-types="password,refresh_token"secret="fbApp" authorities="ROLE_APP" resource-ids="adminProfile" /></oauth:client-details-service><sec:global-method-securitypre-post-annotations="enabled" proxy-target-class="true"><sec:expression-handler ref="oauthExpressionHandler" /></sec:global-method-security><oauth:expression-handler id="oauthExpressionHandler" /><oauth:web-expression-handler id="oauthWebExpressionHandler" /></beans>我們已經配置了/ oauth / token URL來發布訪問和刷新令牌,并且/ api / **映射到服務器上實際受保護的資源。 因此,要訪問與模式/ api / **匹配的任何URL,需要將有效令牌與請求一起傳遞。
身份驗證管理器是進行身份驗證的容器。 在我們的情況下,身份驗證管理器檢查–
- 用戶是否通過身份驗證。
- 用戶是否請求了正確的客戶ID。
- 如果client-id正確,則該用戶是否有權使用它來訪問服務器上的管理配置文件。
請參閱以下代碼段–
<authentication-manager id="clientAuthenticationManager"xmlns="http://www.springframework.org/schema/security"><authentication-provider user-service-ref="clientDetailsUserService" /> </authentication-manager><bean id="clientDetailsUserService"class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService"><constructor-arg ref="clientDetails" /> </bean><!-- OAuth clients allowed to access the protected resources, can be something like facebook, google if we are sharing any resource with them --> <oauth:client-details-service id="clientDetails"><oauth:client client-id="fbApp"authorized-grant-types="password,refresh_token"secret="fbApp" authorities="ROLE_APP" resource-ids="adminProfile" /> </oauth:client-details-service>用戶通過身份驗證后, 授權服務器將調用tokenServices并頒發訪問令牌。
<oauth:authorization-serverclient-details-service-ref="clientDetails" token-services-ref="tokenServices"user-approval-handler-ref="userApprovalHandler"><oauth:authorization-code /><oauth:implicit /><oauth:refresh-token /><oauth:client-credentials /><oauth:password /> </oauth:authorization-server><bean id="tokenServices"class="org.springframework.security.oauth2.provider.token.DefaultTokenServices"><property name="tokenStore" ref="tokenStore" /><property name="supportRefreshToken" value="true" /><property name="accessTokenValiditySeconds" value="120" /><property name="clientDetailsService" ref="clientDetails" /> </bean><bean id="tokenStore"class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" /><bean id="userApprovalHandler"class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler"><property name="tokenServices" ref="tokenServices" /> </bean>在指定客戶端時,請注意我們指定的授權類型,即password 。
<oauth:client-details-service id="clientDetails"><oauth:client client-id="fbApp"authorized-grant-types="password,refresh_token"secret="fbApp" authorities="ROLE_APP" resource-ids="adminProfile" /> </oauth:client-details-service>發出訪問令牌后,我們便可以訪問服務器上受保護的資源,并將其與每個請求一起傳遞。 最后,讓我們看看我們編寫的Spring Controller –
EmployeeController.java
package com.jcombat.controller;import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController;import com.jcombat.bean.Employee;@RestController @RequestMapping(value = "/api/Employee") public class EmployeeController {@RequestMapping(value = "/{name}", method = RequestMethod.GET)public Employee process(@PathVariable("name") String name,@RequestParam(value = "empId", required = false, defaultValue = "00000") final String id) {Employee employee = new Employee();employee.setEmpId(id);employee.setName(name);return employee;} };4.運行應用程序
要運行該應用程序,讓我們首先從授權服務器請求訪問令牌-
http:// localhost:8080 / SecureRESTWithOAuth / oauth / token? grant_type =密碼和client_id = fbApp& client_secret = fbApp& 用戶名 = admin& 密碼 = 123
{ "value":"a7718567-6e38-4be3-aa41-382c90e042e0","expiration":1505631027817,"tokenType":"bearer","refreshToken":{ "value":"7792b077-7ae0-427e-8170-8b1440e5fefd","expiration":1508222907814},"scope":[ ],"additionalInformation":{ },"expiresIn":109,"expired":false }生成訪問令牌后,我們準備將其與服務器上對受保護資源的所有后續請求一起傳遞。
http:// localhost:8080 / SecureRESTWithOAuth / api / Employee / abhimanyu? access_token = 7792b077-7ae0-427e-8170-8b1440e5fefd
5.下載代碼
下載源代碼
翻譯自: https://www.javacodegeeks.com/2017/09/secure-rest-service-oauth2-tokens.html
總結
以上是生活随笔為你收集整理的使用OAuth2令牌的安全REST服务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 红楼梦贾芸是谁的儿子(红楼梦中贾芸的母亲
- 下一篇: 怎么拆掉笔记本电脑主板(怎么拆掉笔记本电