Apache Shiro 与 Spring框架整合

来源:互联网 发布:手机淘宝怎么去评价 编辑:程序博客网 时间:2024/05/12 21:28

1、在web.xml中配制shiroFilter

<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>

2、applicationContext-frame.xml中导入shiro配置文件

<import resource="security/applicationContext-shiro.xml" />

3、配置applicationContext-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-3.1.xsd"    default-lazy-init="true">    <description>Shiro安全配置</description>    <!-- Shiro's main business-tier object for web-enabled applications -->    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">        <property name="realm" ref="shiroDbRealm" />    </bean>    <!-- 項目自定义的Realm -->    <bean id="md5CredentialsMatcher" class="org.apache.shiro.authc.credential.Md5CredentialsMatcher"/>    <bean id="shiroDbRealm"  class="com.xxx.frame.base.security.ShiroDbRealm" lazy-init="true" depends-on="userDao,roleDao">        <property name="cacheManager" ref="shiroEhcacheManager" />        <property name="credentialsMatcher" ref="md5CredentialsMatcher" />        <property name = "authenticationCachingEnabled" value="true" />    </bean>    <!-- Shiro Filter -->    <bean id="myCaptchaFilter" class="com.xxx.frame.base.security.FormAuthenticationCaptchaFilter"/>    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">        <property name="securityManager" ref="securityManager" />        <property name="loginUrl" value="/login" />        <property name="successUrl" value="/main" />        <property name="unauthorizedUrl" value="/error?id=403" />        <property name="filters">            <map>                <entry key="authc" value-ref="myCaptchaFilter"/>            </map>        </property>        <property name="filterChainDefinitionMap" ref="filterMap"/>    </bean>    <bean id="filterMap" class="com.xxx.frame.base.security.ShiroDefinitionSectionMetaSource">        <property name="filterChainDefinitions">            <value>                /logout = logout                /static/** = anon                /images/** = anon                /** = authc            </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、shiro缓存ehcache-shiro.xml

<ehcache updateCheck="false" name="shiroCache">   <defaultCache            maxElementsInMemory="10000"            eternal="false"            timeToIdleSeconds="1200"            timeToLiveSeconds="1200"            overflowToDisk="false"            diskPersistent="false"            diskExpiryThreadIntervalSeconds="1200"            /></ehcache>

5、ShiroDbRealm认证回调函数,登录时调用,需继承AuthorizingRealm

public class ShiroDbRealm extends AuthorizingRealm {    /**     * 认证回调函数,登录时调用.     */    @Override    protected AuthenticationInfo doGetAuthenticationInfo(            AuthenticationToken authcToken) throws AuthenticationException {        Object code = SecurityUtils.getSubject().getSession().getAttribute("validateCode");        SecurityUtils.getSubject().getSession().removeAttribute("validateCode");        UsernamePasswordCaptchaToken token = (UsernamePasswordCaptchaToken) authcToken;        if(!token.getCaptcha().equals(code)){            throw new IncorrectCredentialsException("验证码错误或已过期.");        }else{            User user = userService.getUserByUsername(token.getUsername());            // 增加判断验证码逻辑            if (user != null) {                // 判断MD5加密后的密码是否正确                if (!user.getPassword().equals(MD5.getMD5(new String(token.getPassword())))) {                    throw new IncorrectCredentialsException("密码错误.");                }else{                    // 正确登陆                    ShiroUser shiroUser =  new ShiroUser(user);                    AuthenticationInfo ai = new SimpleAuthenticationInfo(shiroUser, user.getPassword(),getName());                    SecurityUtils.getSubject().getSession().setAttribute("shiroUser",shiroUser);                    return ai;                }            } else {                throw new IncorrectCredentialsException("账号不存在.");            }        }    }    /**     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.     */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(            PrincipalCollection principals) {        Object obj = principals.fromRealm(getName()).iterator().next();        if(obj instanceof ShiroUser){            User user = userService.getUserByUsername(((ShiroUser)obj).username);            if (user != null) {                SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();                // 基于Role的权限信息                info.addRole("" + user.getRole().getId());                // 基于Permission的权限信息                info.addStringPermissions(user.getRole().getPermissionCodeList());                return info;            }        }        return null;    }    public AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {        return super.getAuthorizationInfo(principals);    }    /**     * 自定义Authentication对象,使得Subject除了携带用户的登录名外还可以携带更多信息.     */    public static class ShiroUser implements Serializable{        private static final long serialVersionUID = 1L;        public String id; // 用户ID        public String username; // 登陆名        public String name; // 姓名        public Role role;        public Unit unit;        public ShiroUser(User user) {            this.id = user.getId();            this.username = user.getUsername();            this.name = user.getName();            this.role = user.getRole();            this.unit = user.getUnit();        }        public String getId() {            return id;        }        public String getUsername() {            return username;        }        public String getName() {            return name;        }        public Role getRole() {            return role;        }        public Unit getUnit() {            return unit;        }        /**         * 本函数输出将作为默认的<shiro:principal/>输出.         */        @Override        public String toString() {            return username;        }        /**         * 重载equals,只计算username;         */        @Override        public int hashCode() {            return HashCodeBuilder.reflectionHashCode(this, "username");        }        /**         * 重载equals,只比较username         */        @Override        public boolean equals(Object obj) {            return EqualsBuilder.reflectionEquals(this, obj, "username");        }    }}

至此Apache Shiro基本配置完成

0 0