国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

使用Spring Security Oauth2完成RESTful服務(wù)password認(rèn)證的過程

2019-11-15 00:46:38
字體:
供稿:網(wǎng)友
使用SPRing Security Oauth2完成RESTful服務(wù)passWord認(rèn)證的過程 摘要:Spring Security與Oauth2整合步驟中詳細(xì)描述了使用過程,但它對于入門者有些重量級,比如將用戶信息、ClientDetails、token存入數(shù)據(jù)庫而非內(nèi)存。配置過程比較復(fù)雜,經(jīng)過幾天時間試驗終于成功,下面我將具體的使用Spring Security Oauth2完成password認(rèn)證的過程記錄下來與大家分享。 關(guān)鍵字:HTTP Authentication, rest, spring security, spring mvc 前提:IntelliJ IDEA (13.1.5版本),apache maven(3.2.3版本),Tomcat(7.0.56版本), Spring(3.2.4版本),spring-security-oauth2(2.0.7版本)
一、首先需要使用Spring MVC完成RESTful API的發(fā)布,這一步驟的詳細(xì)情況可見我的另一博文:應(yīng)用Spring MVC 發(fā)布restful服務(wù)是怎樣的一種體驗?二、在/webapp/WEB-INF/web.xml文件中添加相應(yīng)的filter:org.springframework.web.filter.DelegatingFilterProxy,及mapping,具體如以下所示。?<?xml version="1.0"encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <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> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/security.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>restful</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>restful</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping></web-app>?三、在上一步的web.xml文件中可以看到,Spring需要加載/WEB-INF/下的security.xml文件,因此我們在/WEB-INF/下創(chuàng)建security.xml文件,其主要內(nèi)容如下所示。這里比使用Spring Security完成RESTful服務(wù)用戶認(rèn)證中的security.xml文件配置要復(fù)雜得多(見我之前的博文:使用Spring Security完成RESTful服務(wù)用戶認(rèn)證的過程)。注意,這里的配置文件中的<security:http pattern="/abcs/**"><security:intercept-urlpattern="/abcs/**"access="ROLE_ABCS"/>access必須指定一個角色名稱,使用use-expressions="true"isAuthenticated()這里是不允許的。因此,我們需要在實現(xiàn)UserDetails接口、實現(xiàn)getAuthorities()方法時返回此角色名稱,在擁有此角色的用戶認(rèn)證通過后,才可以訪問/abcs/**資源。?<?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:oauth2="http://www.springframework.org/schema/security/oauth2" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:security="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd"> <mvc:annotation-driven/> <mvc:default-servlet-handler/> <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore"/> <bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices"> <property name="tokenStore" ref="tokenStore"/> <property name="supportRefreshToken" value="true"/> <!--<property name="clientDetailsService" ref="clientDetailsService"/>--> </bean> <bean id="clinetAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"/> <bean id="accessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/> <bean id="userApprovalHandler" class="org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler"/> <!--client--> <bean id="clientDetailsService" class="com.anqi.dp.controllers.MyClientDetailsService"/> <bean id="clientDetailsUserDetailsService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService"> <constructor-arg ref="clientDetailsService"/> </bean> <bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter"> <property name="authenticationManager" ref="clientAuthenticationManager"/> </bean> <security:authentication-manager id="clientAuthenticationManager"> <security:authentication-provider user-service-ref="clientDetailsUserDetailsService"/> </security:authentication-manager> <oauth2:authorization-server client-details-service-ref="clientDetailsService" token-services-ref="tokenServices" user-approval-handler-ref="userApprovalHandler"> <oauth2:authorization-code/> <oauth2:implicit/> <oauth2:refresh-token/> <oauth2:client-credentials/> <oauth2:password/> </oauth2:authorization-server> <security:http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager"> <security:anonymous enabled="false"/> <security:http-basic entry-point-ref="clinetAuthenticationEntryPoint"/> <security:custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER"/> <security:access-denied-handler ref="accessDeniedHandler"/> </security:http> <!--client--> <!--user--> <bean id="userService" class="com.anqi.dp.controllers.UserService"/> <security:authentication-manager alias="authenticationManager"> <security:authentication-provider user-service-ref="userService"> <!--<security:password-encoder hash="md5"/>--> </security:authentication-provider> </security:authentication-manager> <!--user--> <oauth2:resource-server id="mobileResourceServer" resource-id="mobile-resource" token-services-ref="tokenServices"/> <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"> <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> <security:http pattern="/abcs/**" create-session="never" entry-point-ref="clinetAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager"> <security:anonymous enabled="false"/> <security:intercept-url pattern="/abcs/**" access="ROLE_ABCS"/> <security:custom-filter ref="mobileResourceServer" before="PRE_AUTH_FILTER"/> <security:access-denied-handler ref="accessDeniedHandler"/> </security:http></beans>?四、當(dāng)然要新建com.anqi.dp.UserService類了,其在security.xml文件中配置其為authenticationManager的authentication-provider。com.anqi.dp.UserService類實現(xiàn)自UserDetailsService接口,它需要實現(xiàn)一loadUserByUsername方法,在實現(xiàn)此方法的過程中,又需要新建MyUserDetails類來實現(xiàn)UserDetails接口。實現(xiàn)loadUserByUsername方法時,可以自己依需要從關(guān)系數(shù)據(jù)庫、NoSQL或者其它存放用戶信息的地方獲取。示例代碼可以查看之前的博文:使用Spring Security完成RESTful服務(wù)用戶認(rèn)證的過程圖1 UserService示例及用戶名密碼登陸。注意,因為配了access="ROLE_ABCS",因此需要在擁有相應(yīng)角色的用戶getAuthorities()方法內(nèi)返回此角色名稱:SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("ROLE_ABCS"); 。還要新建com.anqi.dp.MyClientDetailsService類,其在security.xml文件中配置其為clientAuthenticationManager的authentication-provider。com.anqi.dp.MyClientDetailsService類實現(xiàn)自ClientDetailsService接口,它需要實現(xiàn)一loadClientByClientId方法,在實現(xiàn)此方法的過程中,又需要新建MyClientDetails類來實現(xiàn)ClientDetails接口。實現(xiàn)loadClientByClientId方法時,可以自己依需要從關(guān)系數(shù)據(jù)庫、NoSQL或者其它存放客戶端信息的地方獲取。示例代碼可以查看圖1MyClientDetailsService示例及token獲取。注意,這里的getAuthorities()方法對配的access="ROLE_ABCS"沒有影響。圖1MyClientDetailsService示例及token獲取?五、經(jīng)過以上的步驟,我們就可以進(jìn)行RESTful服務(wù)發(fā)布了,發(fā)布成功后,需要進(jìn)行用戶認(rèn)證的試驗。1、如圖1MyClientDetailsService示例及token獲取所示,我們使用REST Client工具對http://127.0.0.1:8088/restfulservice/oauth/token路徑發(fā)出POST請求,其中需要在Request Parameters中添加client_id、client_secret、grant_type與user_name、password鍵值對。如此,即進(jìn)行了模擬的通過用戶名密碼獲取token的過程。圖2中是client認(rèn)證失敗時的Response,我將client_secret更改后的結(jié)果。圖3是user認(rèn)證失敗時的Response,我將password更改后的結(jié)果。圖4是認(rèn)證成功時的Response。可以看出,在認(rèn)證成功時的Response中存在access_token字段,這就是我們獲取到的token。圖2 client認(rèn)證失敗圖3 user認(rèn)證失敗圖4 認(rèn)證成功2、我們在認(rèn)證成功的條件下,使用上面步驟中返回的access_token對http://localhost:8088/restfulservice/abcs/6?access_token=a7f3e13e-cbb0-417d-a9f8-9764d11db00f進(jìn)行GET請求,即可以成功得到返回結(jié)果,我是使用瀏覽器進(jìn)行HTTP請求的。(具體的邏輯使用Spring MVC的Control完成,見我之前的博文:)。在調(diào)試時,可以看到每次請求,進(jìn)入對應(yīng)Controller后,代碼均會轉(zhuǎn)入UserDetails的String getUsername()方法中。?如果對請求路徑里的access_token值稍作修改,如再對http://localhost:8088/restfulservice/abcs/6?access_token=a7f3e13e-cbb0-417d-a9f8-9764d11db008進(jìn)行GET請求,則返回不到正確結(jié)果,如圖5所示,即返回Invalid access token錯誤。圖5帶正確的access_token值請求返回的結(jié)果圖6 帶不正確的access_token值請求返回的結(jié)果如果刪除access_token,不帶access_token值對http://localhost:8088/restfulservice/abcs/6進(jìn)行GET請求時,返回的錯誤信息如圖7所示。圖7 不帶access_token值請求返回的結(jié)果這就說明,我們的用戶認(rèn)證配置達(dá)到了預(yù)期效果。

最近有各種之前沒有碰到過的問題、技術(shù),有時間整理好分享給大家。

來自王安琪


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 水富县| 麻阳| 荥阳市| 汕尾市| 河源市| 房产| 铜鼓县| 铁力市| 湘潭市| 高唐县| 峨边| 上思县| 北安市| 阿荣旗| 手游| 谷城县| 浏阳市| 武强县| 威宁| 壤塘县| 航空| 阜新市| 白山市| 射阳县| 天水市| 宜城市| 威远县| 合阳县| 稻城县| 仪陇县| 射阳县| 石台县| 白朗县| 平昌县| 唐山市| 织金县| 江陵县| 张掖市| 迁西县| 商都县| 祁门县|