zoukankan      html  css  js  c++  java
  • 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及异常错误码的设计。

  • 相关阅读:
    Python中替换的三种方法
    深入浅出:分布式和集群--转自码农翻身微信公众号
    如何把GitHub中的开源项目导入到Eclipse
    Socket Tools的使用
    LoadRunner 测试Socket接口函数说明
    Apache Jemeter 开发插件
    netstat 查看连接数
    redis缓存机制【转载】
    内存溢出OOM
    transform-translate位移
  • 原文地址:https://www.cnblogs.com/lyh421/p/6405668.html
Copyright © 2011-2022 走看看