第十五章 -------单点登录

Shiro 1.2开始提供了Jasig CAS单点登录的支持,单点登录主要用于多系统集成,即在多个系统中,用户只需要到一个中央服务器登录一次即可访问这些系统中的任何一个,无须多次登录。此处我们使用Jasig CAS v4.0.0-RC3版本:

https://github.com/Jasig/cas/tree/v4.0.0-RC3

 

Jasig CAS单点登录系统分为服务器端和客户端,服务器端提供单点登录,多个客户端(子系统)将跳转到该服务器进行登录验证,大体流程如下:

1、访问客户端需要登录的页面http://localhost:9080/ client/,此时会跳到单点登录服务器https://localhost:8443/ server/login?service=https://localhost:9443/ client/cas;

2、如果此时单点登录服务器也没有登录的话,会显示登录表单页面,输入用户名/密码进行登录;

3、登录成功后服务器端会回调客户端传入的地址:https://localhost:9443/client/cas?ticket=ST-1-eh2cIo92F9syvoMs5DOg-cas01.example.org,且带着一个ticket;

4、客户端会把ticket提交给服务器来验证ticket是否有效;如果有效服务器端将返回用户身份;

5、客户端可以再根据这个用户身份获取如当前系统用户/角色/权限信息。

 

本章使用了和《第十四章 SSL》一样的数字证书。

 

服务器端

我们使用了Jasig CAS服务器v4.0.0-RC3版本,可以到其官方的github下载:https://github.com/Jasig/cas/tree/v4.0.0-RC3下载,然后将其cas-server-webapp模块封装到shiro-example-chapter15-server模块中,具体请参考源码。

 

1、数字证书使用和《第十四章 SSL》一样的数字证书,即将localhost.keystore拷贝到shiro-example-chapter15-server模块根目录下;

 

2、在pom.xml中添加Jetty Maven插件,并添加SSL支持:

Java代码   收藏代码
  1. <plugin>  
  2.   <groupId>org.mortbay.jetty</groupId>  
  3.   <artifactId>jetty-maven-plugin</artifactId>  
  4.   <version>8.1.8.v20121106</version>  
  5.   <configuration>  
  6.     <webAppConfig>  
  7.       <contextPath>/${project.build.finalName}</contextPath>  
  8.     </webAppConfig>  
  9.     <connectors>  
  10.       <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">  
  11.         <port>8080</port>  
  12.       </connector>  
  13.       <connector implementation="org.eclipse.jetty.server.ssl.SslSocketConnector">  
  14.         <port>8443</port>  
  15.         <keystore>${project.basedir}/localhost.keystore</keystore>  
  16.        <password>123456</password>  
  17.         <keyPassword>123456</keyPassword>  
  18.       </connector>  
  19.     </connectors>  
  20.   </configuration>  
  21. </plugin>  

 

3、修改src/main/webapp/WEB-INF/deployerConfigContext.xml,找到primaryAuthenticationHandler,然后添加一个账户:

Java代码   收藏代码
  1. <entry key="zhang" value="123"/>  

其也支持如JDBC查询,可以自己定制;具体请参考文档。

 

4、mvn jetty:run启动服务器测试即可:

访问https://localhost:8443/chapter15-server/login将弹出如下登录页面:


 

输入用户名/密码,如zhang/123,将显示登录成功页面:


 

到此服务器端的简单配置就完成了。 

 

 

客户端

1、首先使用localhost.keystore导出数字证书(公钥)到D:\localhost.cer

Java代码   收藏代码
  1. keytool -export -alias localhost -file D:\localhost.cer -keystore D:\localhost.keystore   

 

2、因为CAS client需要使用该证书进行验证,需要将证书导入到JDK中: 

Java代码   收藏代码
  1. cd D:\jdk1.7.0_21\jre\lib\security  
  2. keytool -import -alias localhost -file D:\localhost.cer -noprompt -trustcacerts -storetype jks -keystore cacerts -storepass 123456   

如果导入失败,可以先把security 目录下的cacerts删掉; 

 

3、按照服务器端的Jetty Maven插件的配置方式配置Jetty插件;

 

4、在shiro-example-chapter15-client模块中导入shiro-cas依赖,具体请参考其pom.xml; 

 

5、自定义CasRealm:

Java代码   收藏代码
  1. public class MyCasRealm extends CasRealm {  
  2.     private UserService userService;  
  3.     public void setUserService(UserService userService) {  
  4.         this.userService = userService;  
  5.     }  
  6.     @Override  
  7.     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {  
  8.         String username = (String)principals.getPrimaryPrincipal();  
  9.         SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();  
  10.         authorizationInfo.setRoles(userService.findRoles(username));  
  11.         authorizationInfo.setStringPermissions(userService.findPermissions(username));  
  12.         return authorizationInfo;  
  13.     }  
  14. }   

CasRealm根据CAS服务器端返回的用户身份获取相应的角色/权限信息。 

 

 

6、spring-shiro-web.xml配置:

Java代码   收藏代码
  1. <bean id="casRealm" class="com.github.zhangkaitao.shiro.chapter13.realm.MyCasRealm">  
  2.     <property name="userService" ref="userService"/>  
  3.     ……  
  4.     <property name="casServerUrlPrefix" value="https://localhost:8443/chapter14-server"/>  
  5.     <property name="casService" value="https://localhost:9443/chapter14-client/cas"/>  
  6. </bean>   

casServerUrlPrefix:是CAS Server服务器端地址;

casService:是当前应用CAS服务URL,即用于接收并处理登录成功后的Ticket的;

 

如果角色/权限信息是由服务器端提供的话,我们可以直接使用CasRealm: 

Java代码   收藏代码
  1. <bean id="casRealm" class="org.apache.shiro.cas.CasRealm">  
  2.     ……  
  3.     <property name="defaultRoles" value="admin,user"/>  
  4.     <property name="defaultPermissions" value="user:create,user:update"/>  
  5.     <property name="roleAttributeNames" value="roles"/>  
  6.     <property name="permissionAttributeNames" value="permissions"/>  
  7.     <property name="casServerUrlPrefix" value="https://localhost:8443/chapter14-server"/>  
  8.     <property name="casService" value="https://localhost:9443/chapter14-client/cas"/>  
  9. </bean>   

defaultRoles/ defaultPermissions:默认添加给所有CAS登录成功用户的角色和权限信息;

roleAttributeNames/ permissionAttributeNames:角色属性/权限属性名称,如果用户的角色/权限信息是从服务器端返回的(即返回的CAS Principal中除了Principal之外还有如一些Attributes),此时可以使用roleAttributeNames/ permissionAttributeNames得到Attributes中的角色/权限数据;请自行查询CAS获取用户更多信息。

 

Java代码   收藏代码
  1. <bean id="casFilter" class="org.apache.shiro.cas.CasFilter">  
  2.     <property name="failureUrl" value="/casFailure.jsp"/>  
  3. </bean>   

CasFilter类似于FormAuthenticationFilter,只不过其验证服务器端返回的CAS Service Ticket。 

 

Java代码   收藏代码
  1. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  2.     <property name="securityManager" ref="securityManager"/>  
  3.     <property name="loginUrl" value="https://localhost:8443/chapter14-server/login?service=https://localhost:9443/chapter14-client/cas"/>  
  4.     <property name="successUrl" value="/"/>  
  5.     <property name="filters">  
  6.         <util:map>  
  7.             <entry key="cas" value-ref="casFilter"/>  
  8.         </util:map>  
  9.     </property>  
  10.     <property name="filterChainDefinitions">  
  11.         <value>  
  12.             /casFailure.jsp = anon  
  13.             /cas = cas  
  14.             /logout = logout  
  15.             /** = user  
  16.         </value>  
  17.     </property>  
  18. </bean>   

loginUrl:https://localhost:8443/chapter15-server/login表示服务端端登录地址,登录成功后跳转到?service参数对于的地址进行客户端验证及登录;

“/cas=cas”:即/cas地址是服务器端回调地址,使用CasFilter获取Ticket进行登录。

 

7、测试,输入http://localhost:9080/chapter15-client地址进行测试即可,可以使用如Chrome开这debug观察网络请求的变化。

 

如果遇到以下异常,一般是证书导入错误造成的,请尝试重新导入,如果还是不行,有可能是运行应用的JDK和安装数字证书的JDK不是同一个造成的:

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

       at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385)

       at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)

       at sun.security.validator.Validator.validate(Validator.java:260)

       at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)

       at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)

       at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)

       at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1323)

       ... 67 more

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

       at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)

       at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)

       at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)

       ... 73 more

      

 

示例源代码:https://github.com/zhangkaitao/shiro-example

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
# sso-shiro-cas spring下使用shiro+cas配置单点登录,多个系统之间的访问,每次只需要登录一次 ## 系统模块说明 1. cas: 单点登录模块,这里直接拿的是cas的项目改了点样式而已 2. doc: 文档目录,里面有数据库生成语句,采用的是MySQL5.0,数据库名为db_test 3. spring-node-1: 应用1 4. spring-node-2: 应用2 其中node1跟node2都是采用spring + springMVC + mybatis 框架,使用maven做项目管理 ## cas集成说明 1.首先采用的是查数据库的方式来校验用户身份的,在cas/WEB-INF/deployerConfigContext.xml中第135行构建了这个类型 ``` xml ``` 其中QueryDatabaseAuthenticationHandler这个类是自定义构建的,在cas/WEB-INF/lib/cas-jdbc-1.0.0.jar里面,有兴趣的同学可以发编译看下,关于几个属性的说明 1. dataSource: 数据源,配置MySQL的连接信息 2. passwordEncoder: 加密方式,这里用的是MD5 3. sql: sql查询语句,这个语句就是根据用户输入的账号查询其密码 #### 以上就是单点登录管理的主要配置 ## 应用系统的配置node1 1. 应用系统采用shiro做权限控制,并且跟cas集成 2. 在/spring-node-1/src/main/resources/conf/shiro.properties 文件中 ``` properties shiro.loginUrl=http://127.0.0.1:8080/cas/login?service=http://127.0.0.1:8081/node1/shiro-cas shiro.logoutUrl=http://127.0.0.1:8080/cas/logout?service=http://127.0.0.1:8081/node1/shiro-cas shiro.cas.serverUrlPrefix=http://127.0.0.1:8080/cas shiro.cas.service=http://127.0.0.1:8081/node1/shiro-cas shiro.failureUrl=/users/loginSuccess shiro.successUrl=/users/loginSuccess ``` 其中shiro.loginUrl 跟 shiro.logoutUrl的前面是cas验证的地址,后面的是我们应用系统的地址,这样配置的方式是为了在访问我们的应用系统的时候,先到cas进行验证,如果验证成功了,cas将重定向到shiro.successUrl 所表示的地址 3.在/spring-node-1/src/main/resources/conf/shiro.xml 文件中 ``` xml /shiro-cas = casFilter /logout = logoutFilter /users/** = user ``` > 其中shiroFilter这个类主要用于需要拦截的url请求,需要注意的是这个是shiro的拦截,我们还需要配置cas的过滤配置casFilter > casRealm这个类是需要我们自己实现的,主要用于shiro的权限验证,里面的属性说明如下 1. defaultRoles: 默认的角色 2. casServerUrlPrefix: cas地址 3. casService: 系统应用地址 最后我们还需要在/spring-node-1/src/main/webapp/WEB-INF/web.xml 文件中配置相关的过滤器拦截全部请求 ``` xml shiroFilter org.springframework.web.filter.DelegatingFilterProxy targetFilterLifecycle true shiroFilter /* ``` ## 系统运行 1. 端口说明,cas:8080,node1:8081,node2:8082,大家可以采用maven提供的tomcat7插件,配置如下: ``` xml org.apache.tomcat.maven tomcat7-maven-plugin 2.1 8081 UTF-8 tomcat7 /node1 ``` 这样的配置,我们甚至都不需要配置tomcat服务器了,建议这种方式 2.各个模块的访问地址 > cas:http://127.0.0.1:8080/cas > node1:http://127.0.0.1:8081/node1 > node2:http://127.0.0.1:8082/node2 3.访问系统 > 输入 http://127.0.0.1:8081/node1/shiro-cas ,进入cas验证 > 输入用户名 admin,密码 admin@2015,验证成功后将会重定向到http://127.0.0.1:8081/node1//users/loginSuccess ,也就是node1系统的主页,里面的节点2代表的是node2系统的主页,你会发现我们不需要登录到node2系统就能访问其中的系统了

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值