2017.2.16 开涛shiro教程-第十七章-OAuth2集成(二)客户端

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

根据下载的pdf学习。

 

开涛shiro教程-第十七章-OAuth2集成

3.客户端

客户端流程可以参照如很多网站的新浪微博登录功能,或其他的第三方帐号登录功能。

1 客户端进行登录操作
2 跳到oauth2服务端,进行登录授权。成功后,服务端返回auth code。
3 客户端使用auth code去服务器换取access token。
4 客户端根据access token得到用户信息,进行客户端的登录绑定。

 

(1)POM依赖

此处我们使用 apache oltu oauth2 客户端实现。

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.xml

  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)代码

代码总览:

 

 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及异常错误码的设计。

 

转载于:https://www.cnblogs.com/lyh421/p/6405668.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值