【Apach shiro】spring 整合Apache shiro

1、新建application-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">


    <bean id="shiroConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:/shiro/shiro.properties"/>
        <property name="ignoreUnresolvablePlaceholders" value="true"/>
    </bean>

    <!-- 整合shiro -->
    <!-- 自定义Realm -->
    <bean id="myRealm" class="com.smile.azxx.shiro.MyRealm">

    </bean>

    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="${shiro.activeRealm}" />
        <property name="cacheManager" ref="cacheManager" />
    </bean>

    <!-- Shiro过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- Shiro的核心安全接口,这个属性是必须的 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 身份认证失败,则跳转到登录页面的配置 -->
        <property name="loginUrl" value="/pages/login.jsp"/>
        <!-- 权限认证失败,则跳转到指定页面 -->
        <property name="unauthorizedUrl" value="/unauthor.jsp"/>
        <!--<property name="filters">-->
            <!--<map>-->
                <!--<entry key="authc" value-ref="shiro" />-->
                <!--<entry key="sysUser" value-ref="sysUserFilter" />-->
                <!--<entry key="kickout" value-ref="kickoutFilter"/>-->
            <!--</map>-->
        <!--</property>-->
        <!-- Shiro连接约束配置,即过滤链的定义 -->
        <property name="filterChainDefinitionMap" ref="shiroFilterChainDefinitionsMap"/>
        <!-- Shiro连接约束配置,即过滤链的定义 -->
        <!--<property name="filterChainDefinitions">-->
        <!--<value>-->
            <!--/login=anon-->
            <!--/static/**=anon-->
            <!--/scripts/**=anon-->
            <!--/**=authc-->
        <!--</value>-->
        <!--</property>-->
    </bean>
    <!--Shiro filter url configs -->
    <bean id="shiroFilterChainDefinitionsMap" class="com.smile.azxx.shiro.ShiroFilterChainDefinitionsMap"/>

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

    <!-- 开启Shiro注解 -->
    <!--<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"-->
          <!--depends-on="lifecycleBeanPostProcessor"/>-->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

    <!-- 用户授权信息Cache -->
    <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" />

    <!-- 如果要实现cas的remember me的功能,需要用到下面这个bean,并设置到securityManager的subjectFactory中 -->
    <!--<bean id="casSubjectFactory" class="org.apache.shiro.cas.CasSubjectFactory"/>-->

    <!-- 基于Form表单的身份验证过滤器 -->
    <bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
        <property name="usernameParam" value="username" />
        <property name="passwordParam" value="password" />
        <property name="rememberMeParam" value="rememberMe" />
        <property name="loginUrl" value="/login" />
    </bean>

    <!-- 自定义拦截器 -->
    <!--<bean id="sysUserFilter" class="com.smile.azxx.shiro.SysUserFilter"></bean>-->

    <!--<bean id="shiro" class="com.smile.azxx.shiro.ShiroFilter"/>-->

    <!--<bean id="kickoutFilter" class="com.myweb.spring.KickoutSessionControlFilter">-->
        <!--<property name="kickoutUrl" value="/api/user/login"/>-->
        <!--<property name="SessionManager" ref="sessionManager"/>-->
        <!--<property name="cacheManager" ref="cacheManager"/>-->
        <!--<property name="kickoutAfter" value="false"/>-->
        <!--<property name="maxSession" value="2"/>-->

    <!--</bean>-->
</beans>
#shiro.properties
shiro.activeRealm = myRealm /static/**=anon /scripts/**=anon /getVerifyImage=anon /login=anon /logout=logout #/**=authc

 


2、在web.xml 添加配置

 <!-- shiro过滤器定义 -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->
            <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>

3、创建 MyRealm 类

package com.smile.azxx.shiro;

import com.smile.azxx.entity.sysmng.User;
import com.smile.azxx.service.sysmng.UserService;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.hibernate.service.spi.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Set;

/**
 * Created by smile on 2018/4/6.
 */
public class MyRealm extends AuthorizingRealm {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private UserService userService;
    /**
     * 为当前登陆成功的用户授予权限和角色,已经登陆成功了
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 根据用户配置用户与权限
        if (principals == null) {
            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
        }
        String username = (String) principals.getPrimaryPrincipal(); //获取用户名
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        List<String> roles = userService.getRoles(username);
        if(roles!=null&&roles.size()>0){
            authorizationInfo.setRoles((Set<String>) roles);
            authorizationInfo.setStringPermissions((Set<String>) userService.getResource(roles));
        }
        return authorizationInfo;
    }

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

        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        String userName = token.getUsername();

        logger.info("请求用户名:"+userName);
        // 清空权限缓存,保证每次登陆都重新同步缓存至最新
        SimplePrincipalCollection key = null;
        Cache<Object, AuthorizationInfo> cache = super.getAuthorizationCache();
        for (Object k : cache.keys()) {
            if (k.toString().equals(userName)) {
                key = (SimplePrincipalCollection) k;
                break;
            }
        }
        if (key != null) {
            cache.remove(key);
        }
//        logger.info("doGetAuthenticationInfoAuthenticationToken............username=" + userName);
        if (userName != null && !"".equals(userName)){
            User user = null;
            try {
                user = userService.getUserByName(userName);
                logger.info("username=" + userName + ";load=" + (user == null ? "false" : "true"));
            } catch (ServiceException e) {
                e.printStackTrace();
            }
            if(user!=null && StringUtils.isNotBlank(user.getUsername())){
                SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),getName());
                SecurityUtils.getSubject().getSession()
                        .setAttribute("c_user", user);
                return authenticationInfo;
            }else {
                throw new UnknownAccountException("该账号未注册,请尝试其他账号!");
            }
        }
        return null;
    }
}

 

posted @ 2018-06-07 09:59  Desperador  阅读(189)  评论(0编辑  收藏  举报