Shiro 权限及登录

Shiro是一款非常强大的安全框架,他可以帮助我们做身份验证,授权,密码学以及会话管理,今天我们就聊聊shiro的授权。

首先我们得确定下授权方案,我们需要用到五张表:用户表、权限表、角色表、用户角色表、角色权限表。

接下来我们开始配置Shiro。

第一步:加入依赖。

第二步:更改web.xml配置。

第三步:添加shiro-shiro.xml配置。

第四步:在springMVC加入Shiro的配置。

第五步:可能会用到缓存,我们添加spring-cache.xml缓存配置。

第六步:添加ehcache.xml配置。

配置结束~

第一步:

扫描二维码关注公众号,回复: 5657006 查看本文章
  <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.5</version>
        </dependency>
    </dependencies>

第二步:

   <!-- shiro的filter -->
    <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>
    <!-- shiro的filter-mapping -->
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

第三步:

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

    <!-- 对应于web.xml中配置的那个shiroFilter -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- Shiro的核心安全接口,这个属性是必须的 -->
        <property name="securityManager" ref="securityManager" />
        <!-- 要求登录时的链接(登录页面地址),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 -->
        <property name="loginUrl" value="/login.jsp" />
        <!-- 登录成功后要跳转的连接(本例中此属性用不到,因为登录成功后的处理逻辑在LoginController里硬编码) -->
        <!-- <property name="successUrl" value="/" ></property> -->
        <!-- 用户访问未对其授权的资源时,所显示的连接。由Spring-MVC控制了,需要在spring-mvc配置文件中配跳转 -->
        <!-- <property name="unauthorizedUrl" value="/error/unauthorized" /> -->

        <property name="filterChainDefinitions">
            <!-- WEB-INF/views/admin 文件夹下的所有jsp页面都需要授权才能访问 -->
            <value>
                /admin/**=authc
            </value>
        </property>

    </bean>


    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>
    <!-- 数据库保存的密码是使用MD5算法加密的,所以这里需要配置一个密码匹配对象 -->
    <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.Md5CredentialsMatcher"></bean>
    <!-- 缓存管理 -->
    <bean id="shiroCacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"></bean>

    <!-- 使用Shiro自带的JdbcRealm类 指定密码匹配所需要用到的加密对象 指定存储用户、角色、权限许可的数据源及相关查询语句 -->
    <bean id="jdbcRealm" class="org.apache.shiro.realm.jdbc.JdbcRealm">
        <property name="credentialsMatcher" ref="credentialsMatcher"></property>
        <property name="permissionsLookupEnabled" value="true"></property>
        <property name="dataSource" ref="dataSource"></property>
        <property name="authenticationQuery"
            value="SELECT password FROM sec_user WHERE user_name = ?"></property>
        <property name="userRolesQuery"
            value="SELECT role_name from sec_user_role left join sec_role using(role_id) left join sec_user using(user_id) WHERE user_name = ?"></property>
        <property name="permissionsQuery"
            value="SELECT permission_name FROM sec_role_permission left join sec_role using(role_id) left join sec_permission using(permission_id) WHERE role_name = ?"></property>
    </bean>

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

    <!-- Shiro的注解配置一定要放在spring-mvc中 -->

</beans>

第四步:

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

    <!-- 导入shiro的相关配置 -->
    <import resource="classpath:spring/spring-shiro.xml" />

    <!-- 扫描路径 -->
    <context:component-scan base-package="com.test.controller">
        <context:include-filter type="annotation"
            expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <!-- 配置根视图 -->
    <mvc:view-controller path="/" view-name="index" />

    <!-- 激活基于注解的配置 @RequestMapping, @ExceptionHandler,数据绑定 ,@NumberFormat , 
        @DateTimeFormat ,@Controller ,@Valid ,@RequestBody ,@ResponseBody等 -->
    <mvc:annotation-driven />

    <!-- 静态资源配置 -->
    <mvc:resources location="/assets/" mapping="/assets/**"></mvc:resources>

    <!-- 视图层配置 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <!-- 开启shiro注解 -->
    <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>

    <!-- 未认证或未授权时跳转必须在springmvc里面配,spring-shiro里的shirofilter配不生效 -->
    <bean
        class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <!--表示捕获的异常 -->
                <prop key="org.apache.shiro.authz.UnauthorizedException">
                    <!--捕获该异常时跳转的路径 -->
                    /error/unauthorized
                </prop>
                <!--表示捕获的异常 -->
                <prop key="org.apache.shiro.authz.UnauthenticatedException">
                    <!--捕获该异常时跳转的路径 -->
                    /error/unauthorized
                </prop>
            </props>
        </property>
    </bean>
</beans>

第五步:

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


    <cache:annotation-driven cache-manager="cacheManager"/>

    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cacheManager-ref="ehcache"/>

    <bean id="ehcache"
          class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
          p:configLocation="classpath:ehcache.xml"/>
</beans>

第六步:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd">

    <diskStore path="java.io.tmpdir/ehcache" />

    <!-- 默认缓存 -->
    <defaultCache 
        maxElementsInMemory="1000" 
        eternal="false"
        timeToIdleSeconds="120" 
        timeToLiveSeconds="120" 
        overflowToDisk="false" />

    <!-- 
        配置自定义缓存
        maxElementsInMemory:缓存中允许创建的最大对象数
        eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。
        timeToIdleSeconds:缓存数据的钝化时间,也就是在一个元素消亡之前,
        两次访问时间的最大时间间隔值,这只能在元素不是永久驻留时有效,
        如果该值是 0 就意味着元素可以停顿无穷长的时间。
        timeToLiveSeconds:缓存数据的生存时间,也就是一个元素从构建到消亡的最大时间间隔值,
        这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。
        overflowToDisk:内存不足时,是否启用磁盘缓存。
        memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。
    -->
    <!-- userService查询用户的缓存 -->
    <cache name="userIsExists" 
        maxElementsInMemory="1000" 
        eternal="false"
        timeToIdleSeconds="120" 
        timeToLiveSeconds="120" 
        overflowToDisk="false"
        memoryStoreEvictionPolicy="LRU" />
    <!-- userService查询用户的缓存 -->
    <cache name="getUserById" 
        maxElementsInMemory="1000" 
        eternal="false"
        timeToIdleSeconds="120" 
        timeToLiveSeconds="120" 
        overflowToDisk="false"
        memoryStoreEvictionPolicy="LRU" />

</ehcache>

**********************************************测试*********************************************

Controller/login:

 UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
        token.setRememberMe(true);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            if (subject.isAuthenticated()) {
                request.getSession().setAttribute("user",user);
                SavedRequest savedRequest = WebUtils.getSavedRequest(request);
                // 获取保存的URL
                if (savedRequest == null || savedRequest.getRequestUrl() == null) {
                    return "admin/home";
                } else {
                    return "forward:" + savedRequest.getRequestUrl();
                }
            } else {
                return "login";
            }
        } catch (IncorrectCredentialsException e) {
            msg = "登录密码错误. Password for account " + token.getPrincipal() + " was incorrect.";
            model.addAttribute("message", msg);
            System.out.println(msg);
        }

权限控制Controller:

 // 只用同时具有user:view和user:create权限才能访问
    @RequiresPermissions(value = { "user:view", "user:create" }, logical = Logical.AND)
    @RequestMapping(value = "/admin/auth")
    public String adminWithAuth() {
        return "admin/withauth";
    }

本文参考http://blog.csdn.net/frankcheng5143/article/details/50836619这篇文章。谢谢各位~

猜你喜欢

转载自blog.csdn.net/qq_41756576/article/details/82142889