shiro(3)- 基于spring框架的Shiro配置(配置详解)

shiro安全控制目录

1. 导入依赖

    <properties>
        <shiro.version>1.2.3</shiro.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${shiro.version}</version>
        </dependency>
    </dependencies>

2. web.xml配置

在web.xml中,将拦截器交由Spring管理。shiro(3)-Filter交由Spring管理-DelegatingFilterProxy

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
    <display-name>helloworld</display-name>
    <!-- 读取spring配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:/spring/applicationContext.xml,
            classpath:/spring/application-shiro.xml,
            classpath:/spring/spring-mybatis.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>


    <!--拦截器由spring容器管理-->
    <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>

    <!-- springMVC核心配置 -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:/spring/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- 拦截设置 -->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

注:设置targetFilterLifecycle=true的含义是保留Filter原有的init和destory方法的调用。

3. Spring配置文件

3.1 配置详解

3.1.1. shiro主过滤器

[费有特][陈][带神你神子]

常用的权限控制:

  • anno:任何人都可以访问;
  • authc:必须登录之后才能访问,不包括remember me(记住密码);
  • user:登录用户才可以访问,包含remember me(记住密码);
  • perm:过滤[权限]规则,这个一般扩展使用(使用自定义过滤器,从数据库查询用户权限),不会使用原生的。
  • roles:过滤[角色]规则,这个一般扩展使用,不会使用原生的。

拦截器优先级:
从上到下,从左到右,如果有匹配的拦截器就会阻断并返回,例如访问js/a.js,第一个拦截器anon符合,就返回true了,不在往下进行匹配了。注意最后一个拦截最后一句是 /**=user意思就是除了上面的那些,其他的所有都要经过。

    <!-- Shiro主过滤器本身功能十分强大,其强大之处就在于它支持任何基于URL路径表达式的、自定义的过滤器的执行 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--shiro的核心安全接口,这是属性是必须的-->
        <property name="securityManager" ref="securityManager"/>
        <!-- 要求登录时的链接,非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 -->
        <property name="loginUrl" value="/login/init"></property>
        <!-- 用户访问未对其授权的资源时,所显示的连接 -->
        <property name="unauthorizedUrl" value="/pages/error/403.jsp"/>
        <!--定义过滤器链-->
        <property name="filterChainDefinitions">
            <value>
                <!--Shiro过滤器链的配置-->
                /login/init/** = anon <!-- 对于登录相关不进行鉴权 -->
                /static/** = anon <!-- 静态资源不进行鉴权 -->
                /** = user
            </value>
        </property>
        <property name="filters">
            <map>
                <entry key="user" value-ref="userFilter"></entry>
            </map>
        </property>
    </bean>
    <!--自定义拦截器-->
    <bean id="userFilter" class="com.springmvc.common.filter.SystemUserFilter"/>

3.1.2. 配置securityManager

   <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!--作用:授权认证,此处为单个realm,若想配置多个,可使用realms参数-->
        <property name="realm" ref="myRealm"/>
        <!--设置会话模式(已过期),需配置适当的WebSessionManager实例-->
        <property name="sessionMode" value="http"/>
        <!--建议关闭,配合/**=user使用时,可未经授权登录系统-->
        <property name="rememberMeManager" ref="rememberMeManager"/>
        <!--配置会话管理器-->
        <property name="sessionManager" ref="defaultWebSessionManager"/>
    </bean>

DefaultWebSecurityManager类主要定义了设置subjectDao,获取会话模式,设置会话模式,设置会话管理器,是否http会话模式等操作。

3.1.3 配置remeberManager

java shiro配置记住密码功能 RememberMe功能怎么实现

Shiro的 rememberMe 功能使用指导(为什么rememberMe设置了没作用?)

<!-- remenberMe配置 -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
  <constructor-arg value="rememberMe" />
  <!-- 浏览器中通过document.cookie可以获取cookie属性,设置了HttpOnly=true,在脚本中就不能的到cookie,可以避免cookie被盗用 -->
  <property name="httpOnly" value="true" />
  <!-- 默认记住7天(单位:秒) -->
  <property name="maxAge" value="604800" />
</bean>
<!-- rememberMe管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
  <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" />
  <property name="cookie" ref="rememberMeCookie" />
</bean>

注:Shiro主过滤器要使用/** = user。

3.1.4Realm配置

AuthorizingRealm为自定义Realm的父类,该类采用的模板方法模式,提供了2个方法供我们实现。
shiro(5)-有状态认证-Realm认证的实现

  • Authentication [噢繁体kei神] 认证;
  • Authorization [额死乱贼神] 授权;
<bean id="myRealm" class="com.springmvc.common.shiro.UserAuthorizingRealm"></bean>

3.1.5 sessionManager配置

DefaultWebSessionManager类主要定义了session的创建,启动,暂停与cookie的关联定义。

<bean id="defaultWebSessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <!--全局session过期时间:30分钟操作会覆盖web.xml文件中的超时时间配置 -->
        <property name="globalSessionTimeout" value="1800000"/>
        <!---session保存到redis中-->
        <property name="sessionDAO" ref="customShiroSessionDAO"/>
        <!-- 所有的session一定要将id设置到Cookie之中,需要提供有Cookie的操作模版 -->
        <property name="sessionIdCookie" ref="simpleCookie"/>
        <!--定时扫描超时session-->
        <!-- session 监听,可以多个。 -->
        <property name="sessionListeners">
           <list>
               <ref bean="customSessionListener"/>
           </list>
         </property>
        <!--session关闭调度器-->
        <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>
         <!-- 需要让此session可以使用该定时调度器进行检测 -->
        <property name="sessionValidationSchedulerEnabled" value="true"/>
        <!--删除过期的session-->
        <property name="deleteInvalidSessions" value="true"/>
    </bean>
    <!--自定义cookie的SessionId-->
    <bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg index="0" value="JSESSIONID_COOKIE"/>
        <property name="httpOnly" value="true"/>
    </bean>
    <!--自定义session监听器-->
    <bean id="customSessionListener" class="om.springmvc.common.filter.CustomSessionListener">
        <property name="shiroSessionRepository" ref="jedisShiroSessionRepository"/>
    </bean>

自定义sessionListener:

public class CustomSessionListener implements SessionListener {
    public void onStart(Session session) {
        
    }

    public void onStop(Session session) {

    }

    public void onExpiration(Session session) {

    }
}

3. 代码中的使用

@Controller
@RequestMapping("/login")
public class LoginAction {
    @RequestMapping(value = {"/init"})
    public ModelAndView init() {
        ModelAndView mv = new ModelAndView("login");
        return mv;
    }
    @RequestMapping("/login")
    public String login(@Param("username") String username,@Param("password") String password) {
        try {
            //创建token
            UsernamePasswordToken token = new UsernamePasswordToken();
            token.setUsername(username);
            token.setPassword(password.toCharArray());
            token.setRememberMe(true);
            //调用验证
            Subject subject = SecurityUtils.getSubject();
            subject.login(token);
            //验证是否登录
            if(subject.isAuthenticated()){
                Session session=subject.getSession();
                //整合redis设置session超时时间setex(sessionId,30*60);
                //返回到页面
                return "redirect:/user";
            }

        } catch (UnknownAccountException e) {
            //无用户名
        }catch (LockedAccountException e){
            //密码没找到
        }catch (IncorrectCredentialsException e){
            //密码不匹配
        }catch (AuthenticationException e){
            //其他登录错误
        }catch (Exception e){
            //未知异常
        }
        return "/error/403";
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。