shiro 單點登陸原理 實例

 

原創 2017年02月08日 17:39:55
  • 4006

Shiro 1.2開始提供了Jasig CAS單點登陸的支持,單點登陸主要用於多系統集成,即在多個系統中,用戶只須要到一箇中央服務器登陸一次便可訪問這些系統中的任何一個,無須屢次登陸。html

 

Jasig CAS單點登陸系統分爲服務器端和客戶端,服務器端提供單點登陸,多個客戶端(子系統)將跳轉到該服務器進行登陸驗證,大致流程以下:java

一、訪問客戶端須要登陸的頁面http://localhost:9080/ client/,此時會跳到單點登陸服務器https://localhost:8443/ server/login?service=https://localhost:9443/ client/cas;git

緣由:客戶端訪問任何地址,都會被shirofilter 攔截,shiro 攔截後發現, 應該會使用authc 進行認證 發現用戶沒有登陸,因此會跳轉到 shiroFilter 配置的loginUrl 頁面github

二、若是此時單點登陸服務器也沒有登陸的話,會顯示登陸表單頁面,輸入用戶名/密碼進行登陸;web

三、登陸成功後服務器端會回調客戶端傳入的地址:https://localhost:9443/client/cas?ticket=ST-1-eh2cIo92F9syvoMs5DOg-cas01.example.org,且帶着一個ticket;spring

四、客戶端會把ticket提交給服務器來驗證ticket是否有效;若是有效服務器端將返回用戶身份;apache

解釋:這個時候 訪問/cas就會被casFileter 攔截 ,casFilter 內部建立 帶ticket 的token,而後 調用subject.login方法,這時候 繼承casRealm 的myrealm  進行處理。服務器

默認認證機制 會去服務器端進行ticket 驗證。網絡

五、客戶端能夠再根據這個用戶身份獲取如當前系統用戶/角色/權限信息。app

 

 

服務器端

咱們使用了Jasig CAS服務器v4.0.0-RC3版本,能夠到其官方的github下載:https://github.com/Jasig/cas/tree/v4.0.0-RC3下載,而後將其cas-server-webapp模塊封裝到shiro-example-chapter15-server模塊中,具體請參考源碼。

 

一、數字證書使用和《第十四章 SSL》同樣的數字證書,即將localhost.keystore拷貝到shiro-example-chapter15-server模塊根目錄下;

 

二、在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>  

 

三、修改src/main/webapp/WEB-INF/deployerConfigContext.xml,找到primaryAuthenticationHandler,而後添加一個帳戶:

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

其也支持如JDBC查詢,能夠本身定製;具體請參考文檔。

 

四、mvn jetty:run啓動服務器測試便可:

訪問https://localhost:8443/chapter15-server/login將彈出以下登陸頁面:


 

輸入用戶名/密碼,如zhang/123,將顯示登陸成功頁面:

 

到此服務器端的簡單配置就完成了。 

 

 

客戶端

一、首先使用localhost.keystore導出數字證書(公鑰)到D:\localhost.cer

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

 

二、由於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刪掉; 

 

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

 

四、在shiro-example-chapter15-client模塊中導入shiro-cas依賴,具體請參考其pom.xml; 

 

五、自定義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服務器端返回的用戶身份獲取相應的角色/權限信息。 

 

 

六、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進行登陸。

 

七、測試,輸入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

相關文章
相關標籤/搜索