2017.2.16 開濤shiro教程-第十七章-OAuth2集成(二)客戶端

原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 java

根據下載的pdf學習。mysql

 

開濤shiro教程-第十七章-OAuth2集成git

3.客戶端github

客戶端流程能夠參照如不少網站的新浪微博登陸功能,或其餘的第三方賬號登陸功能。web

1 客戶端進行登陸操做
2 跳到oauth2服務端,進行登陸受權。成功後,服務端返回auth code。
3 客戶端使用auth code去服務器換取access token。
4 客戶端根據access token獲得用戶信息,進行客戶端的登陸綁定。

 

(1)POM依賴算法

此處咱們使用 apache oltu oauth2 客戶端實現。
spring

1        <dependency>
2             <groupId>org.apache.oltu.oauth2</groupId>
3             <artifactId>org.apache.oltu.oauth2.client</artifactId>
4             <version>0.31</version>
5         </dependency>

附完整pom.xmlsql

  1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3     <parent>
  4         <artifactId>shiro-example</artifactId>
  5         <groupId>com.github.zhangkaitao</groupId>
  6         <version>1.0-SNAPSHOT</version>
  7     </parent>
  8     <modelVersion>4.0.0</modelVersion>
  9     <artifactId>shiro-example-chapter17-client</artifactId>
 10     <packaging>war</packaging>
 11     <name>shiro-example-chapter17-client</name>
 12     <url>http://maven.apache.org</url>
 13     <dependencies>
 14         <dependency>
 15             <groupId>junit</groupId>
 16             <artifactId>junit</artifactId>
 17             <version>3.8.1</version>
 18             <scope>test</scope>
 19         </dependency>
 20 
 21         <dependency>
 22             <groupId>commons-collections</groupId>
 23             <artifactId>commons-collections</artifactId>
 24             <version>3.2.1</version>
 25         </dependency>
 26 
 27 
 28         <dependency>
 29             <groupId>org.apache.oltu.oauth2</groupId>
 30             <artifactId>org.apache.oltu.oauth2.client</artifactId>
 31             <version>0.31</version>
 32         </dependency>
 33 
 34 
 35         <dependency>
 36             <groupId>javax.servlet</groupId>
 37             <artifactId>javax.servlet-api</artifactId>
 38             <version>3.0.1</version>
 39             <scope>provided</scope>
 40         </dependency>
 41         <dependency>
 42             <groupId>javax.servlet.jsp</groupId>
 43             <artifactId>jsp-api</artifactId>
 44             <version>2.2</version>
 45         </dependency>
 46         <dependency>
 47             <groupId>javax.servlet</groupId>
 48             <artifactId>jstl</artifactId>
 49             <version>1.2</version>
 50         </dependency>
 51 
 52 
 53         <dependency>
 54             <groupId>org.apache.shiro</groupId>
 55             <artifactId>shiro-core</artifactId>
 56             <version>1.2.2</version>
 57         </dependency>
 58         <dependency>
 59             <groupId>org.apache.shiro</groupId>
 60             <artifactId>shiro-ehcache</artifactId>
 61             <version>1.2.2</version>
 62         </dependency>
 63         <dependency>
 64             <groupId>org.apache.shiro</groupId>
 65             <artifactId>shiro-web</artifactId>
 66             <version>1.2.2</version>
 67         </dependency>
 68         <dependency>
 69             <groupId>org.apache.shiro</groupId>
 70             <artifactId>shiro-quartz</artifactId>
 71             <version>1.2.2</version>
 72         </dependency>
 73         <dependency>
 74             <groupId>org.apache.shiro</groupId>
 75             <artifactId>shiro-spring</artifactId>
 76             <version>1.2.2</version>
 77         </dependency>
 78 
 79 
 80         <dependency>
 81             <groupId>mysql</groupId>
 82             <artifactId>mysql-connector-java</artifactId>
 83             <version>5.1.25</version>
 84         </dependency>
 85         <dependency>
 86             <groupId>com.alibaba</groupId>
 87             <artifactId>druid</artifactId>
 88             <version>0.2.23</version>
 89         </dependency>
 90 
 91 
 92         <!-- aspectj相關jar包-->
 93         <dependency>
 94             <groupId>org.aspectj</groupId>
 95             <artifactId>aspectjrt</artifactId>
 96             <version>1.7.4</version>
 97         </dependency>
 98         <dependency>
 99             <groupId>org.aspectj</groupId>
100             <artifactId>aspectjweaver</artifactId>
101             <version>1.7.4</version>
102         </dependency>
103 
104         <dependency>
105             <groupId>org.springframework</groupId>
106             <artifactId>spring-context-support</artifactId>
107             <version>4.0.0.RELEASE</version>
108         </dependency>
109 
110         <dependency>
111             <groupId>org.springframework</groupId>
112             <artifactId>spring-jdbc</artifactId>
113             <version>4.0.0.RELEASE</version>
114         </dependency>
115 
116         <dependency>
117             <groupId>org.springframework</groupId>
118             <artifactId>spring-tx</artifactId>
119             <version>4.0.0.RELEASE</version>
120         </dependency>
121 
122         <dependency>
123             <groupId>org.springframework</groupId>
124             <artifactId>spring-webmvc</artifactId>
125             <version>4.0.0.RELEASE</version>
126         </dependency>
127 
128         <!--jackson -->
129         <dependency>
130             <groupId>com.fasterxml.jackson.core</groupId>
131             <artifactId>jackson-databind</artifactId>
132             <version>2.2.3</version>
133         </dependency>
134 
135     </dependencies>
136     <build>
137         <finalName>chapter17-client</finalName>
138         <plugins>
139             <plugin>
140                 <groupId>org.mortbay.jetty</groupId>
141                 <artifactId>jetty-maven-plugin</artifactId>
142                 <version>8.1.8.v20121106</version>
143                 <configuration>
144                     <webAppConfig>
145                         <contextPath>/${project.build.finalName}</contextPath>
146                     </webAppConfig>
147                     <connectors>
148                         <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
149                             <port>9080</port>
150                             <maxIdleTime>60000</maxIdleTime>
151                         </connector>
152                     </connectors>
153                 </configuration>
154             </plugin>
155 
156 
157             <plugin>
158                 <groupId>org.apache.tomcat.maven</groupId>
159                 <artifactId>tomcat7-maven-plugin</artifactId>
160                 <version>2.2</version>
161                 <configuration>
162                     <path>/${project.build.finalName}</path>
163                     <httpPort>9080</httpPort>
164                 </configuration>
165 
166             </plugin>
167         </plugins>
168 
169 
170     </build>
171 </project>
pom.xml

 

(2)代碼apache

代碼總覽:api

 

 OAuth2Token:相似於UsernamePasswordToken,用於存儲oauth2服務端返回的auth code。

 1 import org.apache.shiro.authc.AuthenticationToken;
 2 
 3 public class OAuth2Token implements AuthenticationToken {
 4 
 5     public OAuth2Token(String authCode) {
 6         this.authCode = authCode;
 7     }
 8 
 9     private String authCode;
10     private String principal;
11 
12     //getter、setter略。
13 
14     @Override
15     public Object getCredentials() {
16         return authCode;
17     }
18 }

 

OAuth2AuthenticationFilter :相似於前面提過的FormAuthenticationFilter,用於OAuth客戶端的身份驗證控制。

整個的操做流程,和前面的shiro登陸實際上是很相似的。

1 若是當前用戶尚未身份驗證,首先判斷url中是否有auth code,若是沒有則重定向到服務端進行登陸受權,獲得auth code。
2 有了auth code後,OAuth2AuthenticationFilter 用auth code建立Auth2Token3 Subject.login利用Auth2Token進行登陸。
4 OAuth2Realm 根據OAuth2Token進行相應的登陸邏輯處理。
 1 package com.github.zhangkaitao.shiro.chapter18.oauth2;
 2 
 3 import org.apache.shiro.authc.AuthenticationException;
 4 import org.apache.shiro.authc.AuthenticationToken;
 5 import org.apache.shiro.subject.Subject;
 6 import org.apache.shiro.web.filter.AccessControlFilter;
 7 import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
 8 import org.apache.shiro.web.filter.authc.AuthenticationFilter;
 9 import org.apache.shiro.web.util.WebUtils;
10 import org.springframework.util.StringUtils;
11 
12 import javax.servlet.ServletRequest;
13 import javax.servlet.ServletResponse;
14 import javax.servlet.http.HttpServletRequest;
15 import java.io.IOException;
16 
17 public class OAuth2AuthenticationFilter extends AuthenticatingFilter {
18 
20     private String authcCodeParam = "code";//oauth2 authc code參數名
22     private String clientId;               //客戶端id
24     private String redirectUrl;            //服務器端登陸成功/失敗後重定向到的客戶端地址
26     private String responseType = "code";  //oauth2服務器響應類型
28     private String failureUrl;
29 
30     //setter略。沒有getter。
31 
32     @Override
33     protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
34         HttpServletRequest httpRequest = (HttpServletRequest) request;
35         String code = httpRequest.getParameter(authcCodeParam);//從url中拿到auth code
36         return new OAuth2Token(code);//用auth code建立auth2Token
37     }
38 
39     @Override
40     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
41         return false;
42     }
43 
44     @Override 
45     protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
48         String error = request.getParameter("error");//首先斷定有沒有error,有的話直接重定向到失敗頁面
49         String errorDescription = request.getParameter("error_description");
50         if(!StringUtils.isEmpty(error)) {//若是服務端返回了錯誤
51             WebUtils.issueRedirect(request, response, failureUrl + "?error=" + error + "error_description=" + errorDescription);
52             return false;
53         }
54 
55         Subject subject = getSubject(request, response);
56         if(!subject.isAuthenticated()) {
57             if(StringUtils.isEmpty(request.getParameter(authcCodeParam))) { 58                 //若是用戶沒有身份驗證,且沒有auth code,則重定向到服務端受權
59                 saveRequestAndRedirectToLogin(request, response);
60                 return false;
61             }
62         }
64         return executeLogin(request, response);//執行父類的登陸邏輯,調用Subject.login登陸
65     }
66      
67     @Override//登陸成功後的回調方法
68     protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
69                                      ServletResponse response) throws Exception {
70  issueSuccessRedirect(request, response);
71         return false;
72     }
73 
74     @Override//登陸失敗後的回調方法
75     protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException ae, ServletRequest request,
76                                      ServletResponse response) {
77         Subject subject = getSubject(request, response);
78         if (subject.isAuthenticated() || subject.isRemembered()) {
79             try {
80                 issueSuccessRedirect(request, response);
81             } catch (Exception e) {
82                 e.printStackTrace();
83             }
84         } else {
85             try {
86                 WebUtils.issueRedirect(request, response, failureUrl);
87             } catch (IOException e) {
88                 e.printStackTrace();
89             }
90         }
91         return false;
92     }
93 
94 }

 

OAuth2Realm:

1 OAuth2Realm 首先只支持 OAuth2Token 類型的 Token
2 經過傳入的 auth code 去換取 access token
3 再根據 access token 去獲取用戶信息(用戶名)
4 而後根據此信息建立AuthenticationInfo
5 若是須要 AuthorizationInfo 信息,能夠根據此處獲取的用戶名再根據本身的業務規則去獲取。
 1 package com.github.zhangkaitao.shiro.chapter18.oauth2;
 2 
 3 import org.apache.oltu.oauth2.client.OAuthClient;
 4 import org.apache.oltu.oauth2.client.URLConnectionClient;
 5 import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
 6 import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
 7 import org.apache.oltu.oauth2.client.response.OAuthAccessTokenResponse;
 8 import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
 9 import org.apache.oltu.oauth2.client.response.OAuthResourceResponse;
10 import org.apache.oltu.oauth2.common.OAuth;
11 import org.apache.oltu.oauth2.common.message.types.GrantType;
12 import org.apache.shiro.authc.*;
13 import org.apache.shiro.authz.AuthorizationInfo;
14 import org.apache.shiro.authz.SimpleAuthorizationInfo;
15 import org.apache.shiro.realm.AuthorizingRealm;
16 import org.apache.shiro.subject.PrincipalCollection;
17 
18 public class OAuth2Realm extends AuthorizingRealm {
19 
20     private String clientId;
21     private String clientSecret;
22     private String accessTokenUrl;
23     private String userInfoUrl;
24     private String redirectUrl;
25 
26     //省略setter。
27 
28     @Override
29     public boolean supports(AuthenticationToken token) {
30         return token instanceof OAuth2Token;//表示此Realm只支持OAuth2Token類型
31     }
32 
33     @Override
34     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//受權
35         SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
36         return authorizationInfo;
37     }
38 
39     @Override
40     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//驗證
41         OAuth2Token oAuth2Token = (OAuth2Token) token;
42         String code = oAuth2Token.getAuthCode();
43         String username = extractUsername(code);
44 
45         SimpleAuthenticationInfo authenticationInfo =
46                 new SimpleAuthenticationInfo(username, code, getName());
47         return authenticationInfo;
48     }
49 
50     private String extractUsername(String code) {
51 
52         try {
53             OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
54 
55             OAuthClientRequest accessTokenRequest = OAuthClientRequest
56                     .tokenLocation(accessTokenUrl)
57                     .setGrantType(GrantType.AUTHORIZATION_CODE)
58                     .setClientId(clientId)
59                     .setClientSecret(clientSecret)
60                     .setCode(code)
61                     .setRedirectURI(redirectUrl)
62                     .buildQueryMessage();
63 
64             OAuthAccessTokenResponse oAuthResponse = oAuthClient.accessToken(accessTokenRequest, OAuth.HttpMethod.POST);
65 
66             String accessToken = oAuthResponse.getAccessToken();
67             Long expiresIn = oAuthResponse.getExpiresIn();
68 
69             OAuthClientRequest userInfoRequest = new OAuthBearerClientRequest(userInfoUrl)
70                     .setAccessToken(accessToken).buildQueryMessage();
71 
72             OAuthResourceResponse resourceResponse = oAuthClient.resource(userInfoRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);
73             String username = resourceResponse.getBody();
74             return username;
75         } catch (Exception e) {
76             e.printStackTrace();
77             throw new OAuth2AuthenticationException(e);
78         }
79     }
80 }

 

(3)配置文件spring-config-shiro.xml

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <beans xmlns="http://www.springframework.org/schema/beans"
  3        xmlns:util="http://www.springframework.org/schema/util"
  4        xmlns:aop="http://www.springframework.org/schema/aop"
  5        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6        xsi:schemaLocation="
  7        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  8        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
  9        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
 10 
 11     <!-- 緩存管理器 -->
 12     <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
 13         <property name="cacheManagerConfigFile" value="classpath:ehcache/ehcache.xml"/>
 14     </bean>
 15 
 16     <!-- Realm實現 -->
 17     <bean id="oAuth2Realm" class="com.github.zhangkaitao.shiro.chapter18.oauth2.OAuth2Realm">
 18         <property name="cachingEnabled" value="true"/>
 19         <property name="authenticationCachingEnabled" value="true"/>
 20         <property name="authenticationCacheName" value="authenticationCache"/>
 21         <property name="authorizationCachingEnabled" value="true"/>
 22         <property name="authorizationCacheName" value="authorizationCache"/>
 23 
 24         <property name="clientId" value="c1ebe466-1cdc-4bd3-ab69-77c3561b9dee"/>
 25         <property name="clientSecret" value="d8346ea2-6017-43ed-ad68-19c0f971738b"/>
 26         <property name="accessTokenUrl" value="http://localhost:8080/chapter17-server/accessToken"/>
 27         <property name="userInfoUrl" value="http://localhost:8080/chapter17-server/userInfo"/>
 28         <property name="redirectUrl" value="http://localhost:9080/chapter17-client/oauth2-login"/>
 29     </bean>
 30 
 31     <!-- 會話ID生成器 -->
 32     <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>
 33 
 34     <!-- 會話Cookie模板 -->
 35     <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
 36         <constructor-arg value="sid"/>
 37         <property name="httpOnly" value="true"/>
 38         <property name="maxAge" value="-1"/>
 39     </bean>
 40 
 41     <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
 42         <constructor-arg value="rememberMe"/>
 43         <property name="httpOnly" value="true"/>
 44         <property name="maxAge" value="2592000"/><!-- 30天 -->
 45     </bean>
 46 
 47     <!-- rememberMe管理器 -->
 48     <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
 49         <!-- rememberMe cookie加密的密鑰 建議每一個項目都不同 默認AES算法 密鑰長度(128 256 512 位)-->
 50         <property name="cipherKey"
 51                   value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>
 52         <property name="cookie" ref="rememberMeCookie"/>
 53     </bean>
 54 
 55     <!-- 會話DAO -->
 56     <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
 57         <property name="activeSessionsCacheName" value="shiro-activeSessionCache"/>
 58         <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
 59     </bean>
 60 
 61     <!-- 會話驗證調度器 -->
 62     <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">
 63         <property name="sessionValidationInterval" value="1800000"/>
 64         <property name="sessionManager" ref="sessionManager"/>
 65     </bean>
 66 
 67     <!-- 會話管理器 -->
 68     <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
 69         <property name="globalSessionTimeout" value="1800000"/>
 70         <property name="deleteInvalidSessions" value="true"/>
 71         <property name="sessionValidationSchedulerEnabled" value="true"/>
 72         <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>
 73         <property name="sessionDAO" ref="sessionDAO"/>
 74         <property name="sessionIdCookieEnabled" value="true"/>
 75         <property name="sessionIdCookie" ref="sessionIdCookie"/>
 76     </bean>
 77 
 78     <!-- 安全管理器 -->
 79     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
 80         <property name="realm" ref="oAuth2Realm"/>
 81         <property name="sessionManager" ref="sessionManager"/>
 82         <property name="cacheManager" ref="cacheManager"/>
 83         <property name="rememberMeManager" ref="rememberMeManager"/>
 84     </bean>
 85 
 86     <!-- 至關於調用SecurityUtils.setSecurityManager(securityManager) -->
 87     <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
 88         <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
 89         <property name="arguments" ref="securityManager"/>
 90     </bean>
 91 
 92     <!-- OAuth2身份驗證過濾器 -->
 93     <bean id="oAuth2AuthenticationFilter" class="com.github.zhangkaitao.shiro.chapter18.oauth2.OAuth2AuthenticationFilter">
 94         <property name="authcCodeParam" value="code"/>
 95         <property name="failureUrl" value="/oauth2Failure.jsp"/>
 96     </bean>
 97 
 98     <!-- Shiro的Web過濾器 -->
 99     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
100         <property name="securityManager" ref="securityManager"/>
101         <property name="loginUrl" value="http://localhost:8080/chapter17-server/authorize?client_id=c1ebe466-1cdc-4bd3-ab69-77c3561b9dee&amp;response_type=code&amp;redirect_uri=http://localhost:9080/chapter17-client/oauth2-login"/>
102         <property name="successUrl" value="/"/>
103         <property name="filters">
104             <util:map>
105                 <entry key="oauth2Authc" value-ref="oAuth2AuthenticationFilter"/>
106             </util:map>
107         </property>
108         <property name="filterChainDefinitions">
109             <value>
110                 / = anon
111                 /oauth2Failure.jsp = anon
112                 /oauth2-login = oauth2Authc
113                 /logout = logout
114                 /** = user
115             </value>
116         </property>
117     </bean>
118 
119     <!-- Shiro生命週期處理器-->
120     <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
121 
122 </beans>
spring-config-shiro.xml

 

這裏的OAuth2Realm 須要配置在服務端申請的 clientId clientSecret

 1     <!-- Realm實現 -->
 2     <bean id="oAuth2Realm" class="com.github.zhangkaitao.shiro.chapter18.oauth2.OAuth2Realm">
 3         <property name="cachingEnabled" value="true"/>
 4         <property name="authenticationCachingEnabled" value="true"/>
 5         <property name="authenticationCacheName" value="authenticationCache"/>
 6         <property name="authorizationCachingEnabled" value="true"/>
 7         <property name="authorizationCacheName" value="authorizationCache"/>
 8 
 9         <property name="clientId" value="c1ebe466-1cdc-4bd3-ab69-77c3561b9dee"/>
10         <property name="clientSecret" value="d8346ea2-6017-43ed-ad68-19c0f971738b"/>
11         <property name="accessTokenUrl" value="http://localhost:8080/chapter17-server/accessToken"/>
12         <property name="userInfoUrl" value="http://localhost:8080/chapter17-server/userInfo"/>
13         <property name="redirectUrl" value="http://localhost:9080/chapter17-client/oauth2-login"/>
14     </bean>

 

對應的數據參看server裏的shiro-data.sql

 

而後配置剛剛的OAuth2AuthenticationFilter:

1     <!-- OAuth2身份驗證過濾器 -->
2     <bean id="oAuth2AuthenticationFilter" class="com.github.zhangkaitao.shiro.chapter18.oauth2.OAuth2AuthenticationFilter">
3         <property name="authcCodeParam" value="code"/>
4         <property name="failureUrl" value="/oauth2Failure.jsp"/>
5     </bean>

 

這個OAuth2AuthenticationFilter用來攔截服務端重定向回來的auth code。

這裏的/oauth2-login = oauth2Authc 表示/oauth2-login 地址使用 oauth2Authc 攔截器攔截並進行 oauth2 客戶端受權。

 1 <!-- Shiro的Web過濾器 -->
 2     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
 3         <property name="securityManager" ref="securityManager"/>
 4         <property name="loginUrl" value="http://localhost:8080/chapter17-server/authorize?client_id=c1ebe466-1cdc-4bd3-ab69-77c3561b9dee&amp;response_type=code&amp;redirect_uri=http://localhost:9080/chapter17-client/oauth2-login"/>
 5         <property name="successUrl" value="/"/>
 6         <property name="filters">
 7             <util:map>
 8                 <entry key="oauth2Authc" value-ref="oAuth2AuthenticationFilter"/>
 9             </util:map>
10         </property>
11         <property name="filterChainDefinitions">
12             <value>
13                 / = anon
14                 /oauth2Failure.jsp = anon
15  /oauth2-login = oauth2Authc 16                 /logout = logout
17                 /** = user
18             </value>
19         </property>
20     </bean>

 

(4)測試

a) 訪問地址:http://localhost:9080/chapter17-client/ ,點擊登陸按鈕,跳出以下界面:

 

b) 輸入用戶名,密碼,並點擊登陸並受權。

c) 若是登陸成功,服務端會重定向到客戶端,根據配置文件裏提供的地址爲:http://localhost:9080/chapter17-client/oauth2-login?code=473d56015bcf576f2ca03eac1a5bcc11 。注意這個url是帶着auth code的。

d) 客戶端的OAuth2AuthenticationFilter拿到此auth code,用來建立OAuth2Token,提交給Subject用於登陸。

e) 客戶端的Subject委託給OAuth2Realm進行身份驗證。

f) OAuth2Realm根據token獲取受保護的用戶信息,用於客戶端登陸。

 

至此,OAuth的集成就完成了,只完成了基本功能,沒有進行一些關於異常的檢測。具體的能夠參考新浪微博進行API及異常錯誤碼的設計。

相關文章
相關標籤/搜索