基于Spirng的Shiro安全框架与CAS SSO的集成

来源:互联网 发布:人大网络教育怎么样 编辑:程序博客网 时间:2024/05/05 21:02

首先需要在maven的pom文件中添加依赖

< dependency>     <groupId >org.apache.shiro </groupId >     <artifactId > shiro-cas </artifactId >     <version >${shiro.version} </version >     <exclusions >          <exclusion >            <artifactId > servlet-api </artifactId >            <groupId >javax.servlet </groupId >          </exclusion >          <exclusion >           <artifactId >commons-logging </artifactId >            <groupId >commons-logging </groupId >          </exclusion >    </exclusions >    </dependency >    <dependency >     <groupId >org.apache.shiro </groupId >     <artifactId > shiro-spring</ artifactId>     <version >${shiro.version} </version >    </dependency >    <dependency >     <groupId >org.apache.shiro </groupId >     <artifactId > shiro-ehcache </artifactId >     <version >${shiro.version} </version ></dependency >

在web.xml中添加相应的filter和listener

<!-- The filter-name matches name of a 'shiroFilter' bean inside applicationContext.xml -->    <filter>        <filter-name>shiroFilter</filter-name>        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>        <init-param>            <param-name>targetFilterLifecycle</param-name>            <param-value>true</param-value>        </init-param>    </filter>    <filter>        <filter-name>singleSignOutFilter</filter-name>        <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>    </filter>    <listener>        <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>    </listener>    <filter-mapping>        <filter-name>singleSignOutFilter</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>    <filter-mapping>        <filter-name>shiroFilter</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>

先来看一下shiro的property文件

shiro.session.timeout=1800000shiro.session.validate.timespan=1800000shiro.login.url=http://login.51idc.cn/user/login?service=http://localhost:8086/tickets/shiro-casshiro.logout.url=http://login.51idc.cn/user/logout?service=http://localhost:8086/tickets/ticket/createshiro.login.success.url=http://localhost:8086/homeshiro.casServer.url=http://login.51idc.cn/usershiro.client.cas=http://localhost:8086/tickets/shiro-casshiro.failureUrl=/error.jsp

下面进行applicationContext-shiro.xml的配置,记得在sping的主配置文件中引用此配置

<!-- Shiro Filter    anon:匿名过滤器,不用登录也可以访问    authc:如果继续操作,需要做对应的表单验证否则不能通过    authcBasic:基本http验证过滤,如果不通过,跳转登录页面    logout:登录退出过滤器    noSessionCreation:没有session创建过滤器    perms:权限过滤器    port:端口过滤器,可以设置是否是指定端口如果不是跳转到登录页面    rest:http方法过滤器,可以指定如post不能进行访问等    roles:    角色过滤器,判断当前用户是否指定角色    ssl:请求需要通过ssl,如果不是跳转回登录页    user:如果访问一个已知用户,比如记住我功能,走这个过滤器--><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">        <property name="securityManager" ref="securityManager" />        <!--没有单点登录下的配置:没有权限或者失败后跳转的页面 -->        <!-- <property name="loginUrl" value="/login/toLoginAction"/> -->        <!--有单点登录的配置:登录 CAS 服务端地址,参数 service 为服务端的返回地址 -->        <property name="loginUrl" value="${shiro.login.url}" />        <property name="successUrl" value="${shiro.login.success.url}" />        <property name="filters">            <map>                <entry key="casFilter" value-ref="casFilter" />                <entry key="anon" value-ref="anonymousFilter" />                <entry key="logout" value-ref="logoutFilter" />                <entry key="loginSuccessFilter" value-ref="loginSuccessFilter" />               </map>        </property>        <property name="filterChainDefinitions">            <value>                /shiro-cas = casFilter                /**/*.js = anon                /**/*.css = anon                /static/** = anon                /api/** = anon                /logout = logout                /admin/** = loginSuccessFilter,roles[admin]                /** =loginSuccessFilter,roles[employee]            </value>        </property>    </bean><bean id="casFilter" class="org.apache.shiro.cas.CasFilter">    <!--配置验证错误时的失败页面(Ticket 校验不通过时展示的错误页面) -->    <property name="failureUrl" value="${shiro.failureUrl}" /></bean><bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">    <property name="redirectUrl" value="${shiro.logout.url}" /></bean><bean id="anonymousFilter" class="org.apache.shiro.web.filter.authc.AnonymousFilter" /><!-- 自定义的filter--><bean id="loginSuccessFilter" class="com.anchnet.tickets.web.filters.LoginSuccessFilter" /><!-- Shiro's main business-tier object for web-enabled applications -->        <property name="sessionManager" ref="defaultWebSessionManager"/>        <property name="realms">            <list>                <ref bean="casRealm" />            </list>        </property>        <property name="subjectFactory" ref="casSubjectFactory" />        <property name="cacheManager" ref="shiroEhcacheManager" />    </bean><bean id="casRealm" class="com.anchnet.tickets.service.account.CustomCASRealm">        <property name="defaultRoles" value="ROLE_USER" />        <property name="casServerUrlPrefix" value="${shiro.casServer.url}" />        <!--客户端的回调地址设置,必须和上面的shiro-cas过滤器拦截的地址一致 -->        <property name="casService" value="${shiro.client.cas}" /></bean><!--Define the realm you want to use to connect to your back-end security     datasource: --><bean id="casSubjectFactory" class="org.apache.shiro.cas.CasSubjectFactory" /><!-- default web session manager --><bean id="defaultWebSessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">    <property name="globalSessionTimeout" value="${shiro.session.timeout}"/>    <property name="sessionIdCookie" ref="simpleCookie"/>    <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>    <property name="sessionValidationSchedulerEnabled" value="true"/>    <property name="deleteInvalidSessions" value="true"/></bean><bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie">    <constructor-arg index="0" value="JSESSIONID_COOKIE"/>    <property name="httpOnly" value="true"/></bean><bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler">    <property name="sessionManager" ref="defaultWebSessionManager"/>    <property name="interval" value="${shiro.session.validate.timespan}"/></bean><!-- 用户授权信息Cache, 采用EhCache -->    <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">        <property name="cacheManagerConfigFile" value="classpath:cache/ehcache-shiro.xml" />    </bean><!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /><!--AOP式方法级权限检查 --><!--Enable Shiro Annotations for Spring-configured beans. Only run after --><!--the lifecycleBeanProcessor has run: --><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>

上面的用户授权的cache采用ehcache,以下是ehcache-shiro.xml的配置

<ehcache updateCheck="false" name="shiroCache">    <!-- http://ehcache.org/ehcache.xml -->   <defaultCache            maxElementsInMemory="10000"            eternal="false"            timeToIdleSeconds="120"            timeToLiveSeconds="120"            overflowToDisk="false"            diskPersistent="false"            diskExpiryThreadIntervalSeconds="120"            /></ehcache>

下面详细介绍 CasRealm bean的实现

import java.io.Serializable;import java.util.Map;import org.apache.commons.lang3.StringUtils;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.authz.UnauthorizedException;import org.apache.shiro.cas.CasRealm;import org.apache.shiro.subject.PrincipalCollection;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.google.common.base.Objects;import com.google.common.collect.ImmutableList;public class CustomCASRealm extends CasRealm {    private static Logger logger = LoggerFactory            .getLogger(CustomCASRealm.class);    // @Autowired    protected AccountService accountService;    @Override    protected AuthorizationInfo doGetAuthorizationInfo(            PrincipalCollection principals) {        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();        String loginName = (String) principals.getPrimaryPrincipal();        if (loginName == null) {            throw new UnauthorizedException("无效的凭证");        }        try {            Map rolesMaps = (Map) principals.asList().get(1);            String roles = (String) rolesMaps.get("role");            if (roles.length() > 0) {                roles = roles.substring(1);                roles = roles.substring(0, roles.length() - 1);                logger.debug("!!!!! get roles:{}", roles);                authorizationInfo.addRoles(ImmutableList.copyOf(StringUtils.split(roles, ", ")));            } else {                logger.debug("user {} has no roles!!!", loginName);            }        } catch (Exception e) {            e.printStackTrace();            throw new UnauthorizedException("无效的凭证");        }        return authorizationInfo;    }
0 0
原创粉丝点击