《权限系列shiro+cas》---封装公共验证模块

前言

  • 小编最近正在优化权限框架,应对的需求是:在一个分布式系统中,要有单点登录功能,还得有集中的权限认证。于是技术选型就找到了shiro和Cas,shiro是Apache旗下的开源授权框架,而Cas是Yale 大学发起的一个企业级的、开源的项目,旨在为 Web 应用系统提供一种可靠的单点登录解决方法(属于 Web SSO)。做授权的框架还有Spring Security,置于Spring Security和Shiro的区别,大家自己去查查吧,下面小编进入正题。

源码地址

点击这里,去小编的GitHub上下载源码

shiro和cas的关系

  • 用cas实现认证(登录),用shiro实现授权。

项目之间的依赖关系

  • shiro-cas-authority是公共验证模块,它是一个jar工程,主要让各个应用程序来引用,应用程序一(applicationOne)和应用程序二(applicationTwo)引用shiro-cas-authority,当各个应用程序访问访问需要权限的资源时,程序就会跳到shiro-cas-authority来进行权限验证,其实就是利用shiro来授权。

配置shiro的核心过滤器和cas单点登出过滤器

  • 在公共验证模块:shiro-cas-authority是没有web.xml的,我们将这个模块打包成jar包供各个应用程序使用,所以web.xml是在各个应用程序中的。
<!-- shiro的核心过滤器----------begin -->
<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-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<!-- shiro的核心过滤器----------end -->
<!-- 配置单点登出   begin-->
<listener>
    <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<filter>
    <filter-name>singleSignOutFilter</filter-name>
    <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>singleSignOutFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 单点登出----------------end -->

shiro与spring整合

配置spring-shiro-authority.xml

<!-- Shiro Filter -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager" />
    <!-- 设定用户的登录链接,这里为cas登录页面的链接地址可配置回调地址 -->
    <property name="loginUrl" value="${shiro.loginUrl}" />
    <property name="filters">
        <map>
            <!-- 添加casFilter到shiroFilter -->
            <entry key="casFilter" value-ref="casFilter" />
            <entry key="logoutFilter" value-ref="logoutFilter" />
        </map>
    </property>
    <property name="filterChainDefinitions">
        <value>
            /shiro-cas = casFilter
            /logout = logoutFilter
            /**=user
        </value>
    </property>
</bean>

<bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
    <!-- 配置验证成功是的URL -->
    <property name="successUrl" value="${shiro.successUrl}" />
    <!-- 配置验证错误时的失败URL -->
    <property name="failureUrl" value="${shiro.failureUrl}" />
</bean>

<bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
    <!-- 配置验证错误时的失败页面 -->
    <property name="redirectUrl" value="${shiro.logoutUrl}" />
</bean>

<bean id="casRealm" class="com.spring.mybatis.realm.UserRealm">
    <!-- 认证通过后的默认角色 -->
    <!-- <property name="defaultRoles" value="ROLE_USER" /> -->
    <!-- cas服务端地址前缀 -->
    <property name="casServerUrlPrefix" value="${shiro.cas.serverUrlPrefix}" />
    <!-- 应用服务地址,用来接收cas服务端票据 -->
    <property name="casService" value="${shiro.cas.service}" />
</bean>

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

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

<bean
    class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="securityManager" />
</bean>

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>

<bean
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod"
        value="org.apache.shiro.SecurityUtils.setSecurityManager"></property>
    <property name="arguments" ref="securityManager"></property>
</bean>

spring核心配置文件spring-context-authority.xml

<context:component-scan base-package="com.spring.mybatis"/>

<!--  自动注入properties属性文件 -->
  <bean id="configProperties111" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
   <property name="locations">
     <list>
       <value>classpath:conf/jdbc.properties</value>
     <!--   <value>classpath:conf/shiro.properties</value> -->
     </list>
   </property>
  </bean>
  <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
      <property name="properties" ref="configProperties111" />
  </bean>  

  <!-- mybatis配置 -->
  <import resource="spring-mybatis-authority.xml"/>
  <!-- shiro配置 -->
  <import resource="spring-shiro-authority.xml"/>

核心Realm的实现

public class UserRealm extends CasRealm {
    @Resource
    private RoleService roleService;
    @Resource
    private UserService userService;

    protected final Map<String, SimpleAuthorizationInfo> roles = new ConcurrentHashMap<String, SimpleAuthorizationInfo>();

    /**
     * 设置角色和权限信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        String account = (String) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = null;
        if (authorizationInfo == null) {
            authorizationInfo = new SimpleAuthorizationInfo();
            List<String> permissions = roleService.getPermissions(account);
            authorizationInfo.addStringPermissions(permissions);
            authorizationInfo.addRoles(roleService.getRoles(account));
            roles.put(account, authorizationInfo);
        }

        return authorizationInfo;
    }


    /**
     * 1、CAS认证 ,验证用户身份
     * 2、将用户基本信息设置到会话中
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {

        AuthenticationInfo authc = super.doGetAuthenticationInfo(token);

        String account = (String) authc.getPrincipals().getPrimaryPrincipal();

        User user = userService.getUserByAccount(account);
     SecurityUtils.getSubject().getSession().setAttribute("user", user);

        return authc;
    }
}
  • 这个核心UserRealm是shiro控制权限的核心,在这个类中,我们将某个用户的拥有的资源查询出来,放到SimpleAuthorizationInfo的对象中,当我们访问后台方法时,shiro会自动根据SimpleAuthorizationInfo对象的中拥有的资源信息进行比对,检查用户是否有权限访问该资源。

小结

  • 小编并没有将代码完全贴出来,要是每条线都贴出来就太麻烦了,大家可以去下载源码(源码地址已经给出),读者可以在调试项目的时候可以加深理解。

猜你喜欢

转载自blog.csdn.net/u013067402/article/details/73823839