Cas单点登录(整合shiro版本)

单点登录:Single Sign On,简称SSO,SSO使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

CAS框架:CAS(Central Authentication Service)是实现SSO单点登录的框架。
逻辑关系图:(注:图为转载)

分析:
1.图中用户访问cas客户端;
2.需要登录时,重定向到Cas-Server(Cas服务),其中service为Cas-Client路径
(用于Cas-Server执行完后返回到指定路径);
3.cas-server认证用户信息,并生成一个ticket返回给用户;
4.用户使用此ticket访问Cas-Client(连接了Cas-Server具体应用);
5.Cas-Client使用ticket再次访问Cas-Server进行认证;
6.认证成功后返回Server指定路径到Cas-Client,并返回具体登录用户信息,流程结束。

这是原生Cas的一套流程,那么我们需要集成到已经使用Shiro框架的应用中,如何进行无缝衔接呢?

具体流程:
对于Cas-Server就不多说了,官网下载下来后,修改验证用户信息的配置(从数据库中读取数据进行
身份认证),修改配置文件-deployerConfigContext:
(其中deployerConfigContext.xml文件是CAS专门提出来的供用户修改的配置,其他配置不建议修改)
[html]  view plain  copy
  1. <bean id="primaryAuthenticationHandler"  
  2.           class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">  
  3.         <property name="dataSource" ref="dataSource" />    
  4.         <property name="sql" value="select password from userwhere userName=?" />    
  5.     </bean>  
  6.       
  7.     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">    
  8.        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
  9.        <property name="url" value="jdbc:mysql://127.0.0.1:3306/**?characterEncoding=utf8" />    
  10.        <property name="username" value="**" />    
  11.        <property name="password" value="**" />    
  12.     </bean>   
注意:其中需要引入包cas-server-support-jdbc-4.0.0.jar(版本号极为重要,与cas-server-core版本一致即可)
还需要引入mysql-connector-java-5.1.34.jar(连接mysql)
连接Cas-Server的使用了Shiro的应用项目连接的整体操作流程,如下:
1.首先需要引入包shiro-cas这个包是shiro和cas连接的通道;
2.修改项目中shiroRealm(自定义的登录验证类,里面包含登录认证、权限认证)
[java]  view plain  copy
  1. /** 
  2.  * shiro登录实现类  
  3.  *  
  4.  */  
  5. //重点是集成CasRealm  
  6. public class ShiroRealm extends CasRealm {  
  7.       
  8.     private Logger log = LoggerFactory.getLogger(ShiroRealm.class);  
  9.       
  10.     private TicketValidator ticketValidator;    
  11.       
  12.      protected TicketValidator ensureTicketValidator()    
  13.         {    
  14.             if(ticketValidator == null)    
  15.                 ticketValidator = createTicketValidator();    
  16.             return ticketValidator;    
  17.         }    
  18.       
  19.     @Override  
  20.     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {  
  21.         CasToken casToken = (CasToken) authcToken;    
  22.         if (authcToken == null)    
  23.             return null;    
  24.         String ticket = (String) casToken.getCredentials();    
  25.         TicketValidator ticketValidator = ensureTicketValidator();  
  26.       try    
  27.         {    
  28.             Assertion casAssertion = ticketValidator.validate(ticket, getCasService());    
  29.             AttributePrincipal casPrincipal = casAssertion.getPrincipal();    
  30.             String userId = casPrincipal.getName();    
  31.             log.debug("Validate ticket : {} in CAS server : {} to retrieve user : {}"new Object[] {    
  32.                 ticket, getCasServerUrlPrefix(), userId    
  33.             });    
  34.             Map<String, Object> attributes = casPrincipal.getAttributes();    
  35.             casToken.setUserId(userId);    
  36.             String rememberMeAttributeName = getRememberMeAttributeName();    
  37.             String rememberMeStringValue = (String)attributes.get(rememberMeAttributeName);    
  38.             boolean isRemembered = rememberMeStringValue != null && Boolean.parseBoolean(rememberMeStringValue);    
  39.             if(isRemembered)    
  40.                 casToken.setRememberMe(true);    
  41.             /**  此处是封装用户信息 
  42.             sUsr su = new sUsr(); 
  43.             su.setUsrCde(userId); 
  44.             sUsr susr = isUsrService.findByCode(su); 
  45.             AccessTokenInfo atInfo = new AccessTokenInfo(); 
  46.             atInfo.setUsrCde(userId); 
  47.             //获取apikey 
  48.             AccessTokenInfo ati = accessTokenInfoService.selectOneByObject(atInfo); 
  49.             //构建ShiroUserAccount 
  50.             ShiroUserAccount sua = new ShiroUserAccount(susr,ati); 
  51.             */  
  52.             List<Object> principals = CollectionUtils.asList(new Object[] {    
  53.                 sua, attributes    
  54.             });                
  55.             PrincipalCollection principalCollection = new SimplePrincipalCollection(principals, getName());    
  56.             return new SimpleAuthenticationInfo(principalCollection, ticket);    
  57.         }    
  58.         catch(TicketValidationException e)    
  59.         {    
  60.             throw new CasAuthenticationException((new StringBuilder()).append("Unable to validate ticket [").append(ticket).append("]").toString(), e);    
  61.         }         
  62.     }  
  63.   
  64.   
  65.     @Override  
  66.     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {  
  67.         SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();  
  68.         //获取登录用户的Shiro对象  ---主体身份信息(验权)  
  69.         ShiroUserAccount shiroUser = (ShiroUserAccount)principal.getPrimaryPrincipal();   
  70.         //断言,若对象为空则直接抛出异常  
  71.         Assert.notNull(shiroUser,"找不到principal中的SessionVariable---shiroUser");  
  72.         //添加用户拥有的role  
  73.         addRoles(info,shiroUser);  
  74.         addPermissions(info,shiroUser);  
  75.         return info;  
  76.     }  
  77.       
  78. }  

3.配置shiro.xml文件:
shiroRealm:
[html]  view plain  copy
  1. <bean id="shiroRealm" class="com.**.ShiroRealm">  
  2.         <!-- cas服务端地址前缀 -->  
  3.     <property name="casServerUrlPrefix" value="http://127.0.0.1:8080/SSO" />  
  4.     <!-- 应用服务地址,用来接收cas服务端票据,客户端的cas入口 -->  
  5.     <property name="casService" value="http://127.0.0.1:8585/**/shiro-cas" />  
  6.    </bean>    

shiroFilter:
[html]  view plain  copy
  1. <!--shiro过滤器配置,bean的id值须与web中的filter-name的值相同-->    
  2.     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">    
  3.         <property name="securityManager" ref="securityManager" />    
  4.         <span style="white-space:pre;"> </span><!-- 验证用户未登录时跳转的登录地址 -->  
  5.         <property name="loginUrl" value="http://127.0.0.1:8080/SSO/login?service=http://127.0.0.1:8585/**/shiro-cas" />  
  6.         <property name="successUrl" value="" />  
  7.         <!-- 验证用户权限的跳转地址 -->  
  8.         <property name="unauthorizedUrl" value="/" />  
  9.            
  10.          <property name="filters">    
  11.            <span style="white-space:pre;">  </span>    <map>   
  12.                 <!--添加cas的过滤器到shiro  -->    
  13.                 <span style="white-space:pre;"> </span><entry key="casFilter" value-ref="casFilter"/>    
  14.                 <span style="white-space:pre;"> </span><!--添加登出过滤  -->    
  15.                 <span style="white-space:pre;"> </span><entry key="logoutFilter" value-ref="logoutFilter" />  
  16.             <span style="white-space:pre;"> </span>   </map>    
  17.         </property>  
  18.            
  19.         <property name="filterChainDefinitions">    
  20.             <value>   
  21.                 /shiro-cas = casFilter                
  22.                 /person/**=authc  
  23.             </value>    
  24.         </property>    
  25.     </bean>        
casFilter:
[html]  view plain  copy
  1. <bean id="casFilter" class="org.apache.shiro.cas.CasFilter">  
  2.         <!-- 配置验证错误时的失败页面 -->  
  3.         <property name="failureUrl" value="http://127.0.0.1:8080/SSO/login?service=http://127.0.0.1:8585/themis_front/shiro-cas" />  
  4.         <property name="successUrl" value="/themis/ReviewQuery" />  
  5.     </bean>  
logoutFilter:
[html]  view plain  copy
  1. <bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">  
  2.         <!-- 配置验证错误时的失败页面 -->  
  3.         <property name="redirectUrl" value="http://127.0.0.1:8080/SSO/logout?service=http://127.0.0.1:8585/themis_front/shiro-cas" />  
  4.     </bean>  

cas针对subject工厂配置:
[html]  view plain  copy
  1. <bean id="casSubjectFactory" class="org.apache.shiro.cas.CasSubjectFactory"></bean>  
  2.       
  3.     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">    
  4.         <!--单个realm使用realm,如果有多个realm,使用realms属性代替-->    
  5.         <property name="realm" ref="shiroRealm" />    
  6.           <!-- session 管理器 -->  
  7.         <property name="sessionManager" ref="sessionManager" />  
  8.         <!-- 缓存管理器 -->  
  9.         <property name="cacheManager" ref="shiroCacheManager" />  
  10.         <property name="subjectFactory" ref="casSubjectFactory"></property>  
  11.     </bean>    
如下是shiro剩余的基本配置:
[html]  view plain  copy
  1.     <!-- session管理器 -->  
  2. <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">  
  3.     <!-- 超时时间 -->  
  4.     <property name="globalSessionTimeout" value="1800000"/>  
  5.     <!-- session存储的实现 -->  
  6.     <property name="sessionDAO" ref="shiroSessionDao"/>  
  7.     <!-- sessionIdCookie的实现,用于重写覆盖容器默认的JSESSIONID -->  
  8.     <property name="sessionIdCookie" ref="sharesession"/>  
  9.     <!-- 定时检查失效的session -->  
  10.     <property name="sessionValidationSchedulerEnabled" value="true" />  
  11. </bean>  
  12.   
  13.  <!-- sessionIdCookie的实现,用于重写覆盖容器默认的JSESSIONID -->  
  14.   <bean id="sharesession" class="org.apache.shiro.web.servlet.SimpleCookie">  
  15.       <!-- cookie的name,对应的默认是 JSESSIONID -->  
  16.       <constructor-arg name="name" value="SHAREJSESSIONID"/>  
  17.     <!-- 记住我cookie生效时间30天 -->  
  18.     <property name="maxAge" value="2592000" />  
  19.   </bean>  
  20.     
  21.   
  22.  <!-- session存储的实现 -->  
  23.   <bean id="shiroSessionDao" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO" />  
  24.   <!-- 缓存管理实现 -->  
  25.   <bean id="shiroCacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" />  
  26.        
  27.    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->      
  28.    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>      
  29.          
  30.    <!-- AOP式方法级权限检查  -->    
  31.    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">      
  32.        <property name="proxyTargetClass" value="true" />      
  33.    </bean>      
  34.        
  35.    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">      
  36.        <property name="securityManager" ref="securityManager"/>      
  37.    </bean>  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值