cas client 4.0 整合 shiro

概念或其它内容可以参考我一系列的博客相关文章 http://sgq0085.iteye.com/category/302777

1.Maven主要依赖

<dependency>
    <groupId>org.jasig.cas.client</groupId>
    <artifactId>cas-client-core</artifactId>
    <version>3.3.3</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.2.3</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>1.2.3</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-cas</artifactId>
    <version>1.2.3</version>
</dependency>

2.web.xml

<filter>
    <filter-name>CAS Validation Filter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetBeanName</param-name>
        <param-value>shiroFilter</param-value>
    </init-param>
    <!-- targetFilterLifecycle设为true是将filter放入web容器中成为真正意义上的filter。
         否则只是个代理filter,不具有filter的生命周期,因此无法执行filter的init、destroy方法 -->
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

3.shiro的Spring配置文件

1.主要是配置了casFilter 和 DefaultWebSecurityManager的subjectFactory参数;

2.casFilter 中 failureUrl 参数对应的地址 cas-failure需要自己实现,当登录认证失败的时候,会访问这个地址,可以通过该地址将该请求指向一个错误页面;LoginController中实现

3.注意Bean ShiroFilterFactoryBean属性loginUrl的值是 cas服务器地址,并将当前项目登录地址(注意那个/login)作为参数传入进去的。这里 /login和下面filterChainDefinitions中/login = cas保持一直;

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
    <!-- 读取配置文件 -->
    <context:property-placeholder location="classpath*:cas.properties" ignore-unresolvable="true"/>

    <bean name="singleSignOutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>

    <bean name="assertionThreadLocalFilter" class="org.jasig.cas.client.util.AssertionThreadLocalFilter"/>

    <bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
        <!-- cas-failure 通过SpringMVC 跳转JSP -->
        <property name="failureUrl" value="cas-failure"/>
    </bean>

    <!-- Shiro's main business-tier object for web-enabled applications -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="shiroCasRealm"/>
        <property name="cacheManager" ref="shiroEhcacheManager"/>
        <property name="subjectFactory" ref="casSubjectFactory"/>
    </bean>

    <!-- 項目自定义的Realm -->
    <bean id="shiroCasRealm" class="com.gqshao.cas.realm.MyCasRealm">
        <property name="casServerUrlPrefix" value="https://sso.gqshao.com:8443/cas-server"/>
        <property name="casService" value="http://sso.gqshao.com:8090/client/login"/>
    </bean>

    <bean id="casSubjectFactory" class="org.apache.shiro.cas.CasSubjectFactory"/>

    <!-- Shiro Filter -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <!-- 用于调用Controller -->
        <property name="loginUrl"
                  value="https://sso.gqshao.com:8443/cas-server/login?service=http://sso.gqshao.com:8090/client/login"/>
        <property name="successUrl" value="/"/>
        <!-- 自己实现的formAuthcFilter,加入key type -->
        <property name="filters">
            <util:map>
                <entry key="cas" value-ref="casFilter"/>
            </util:map>
        </property>
        <property name="filterChainDefinitions">
            <value>
                /login = cas
                /logout = logout
                /static/** = anon
                /cas-failure = anon
                /** = user
            </value>
        </property>
    </bean>

    <!-- 用户授权信息Cache, 采用EhCache -->
    <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:security/ehcache-shiro.xml"/>
    </bean>

    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <!-- AOP式方法级权限检查 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor">
        <property name="proxyTargetClass" value="true"/>
    </bean>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>
</beans>

 4.LoginController

1.failure方法是登录失败指定跳转到某条失败页面中

2.logoutUrl用于返回登出地址,实际的地址应该为https://sso.gqshao.com/adp-cas/logout?service=http://sso.gqshao.com:8080/adp-web/logout,/logout配置在shiro配置文件中filterChainDefinitions下ShiroFilterFactoryBean中

@Controller
public class LoginController {

    @Value("${client.logoutUrl}")
    public String logoutUrl;

    @RequestMapping("/cas-failure")
    public String failure() {
        return "error/casFailure";
    }

    @RequestMapping("/logout-url")
    @ResponseBody
    public String logoutUrl() {
        return logoutUrl;
    }
}

5.Shiro的Realm实现

继承CasRealm

public class MyCasRealm extends CasRealm {


    /**
     * 认证回调函数,登录时调用.
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) {
        return super.doGetAuthenticationInfo(authcToken);
    }

    /**
     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
     */
    @Override
    @SuppressWarnings("unchecked")
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        List<Object> listPrincipals = principals.asList();
        String name = listPrincipals.get(0).toString();
        Map<String, String> attributes = (Map<String, String>) listPrincipals.get(1);
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        Set<String> roles = Sets.newHashSet("admin","operator");
        authorizationInfo.setRoles(roles);
        Set<String> permissions = Sets.newHashSet("show-info");
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }
}

6.注意

1.通过shiro-cas整合后AssertionHolder不可用

2.实际部署在tomcat时,Windows环境下catalina.bat文件中需要添加set JAVA_OPTS=%JAVA_OPTS% -Dfile.encoding=UTF-8;Linux环境中catalina.sh文件中配置JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8"

猜你喜欢

转载自sgq0085.iteye.com/blog/2200319