Shiro系列之Shiro+Spring MVC整合

简介: 原文链接:http://blog.csdn.net/chris_mao/article/details/49288251

第一步,Shiro Filter

在web.xml文件中增加以下代码,确保Web项目中需要权限管理的URL都可以被Shiro拦截过滤。


<!-- 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>  
    <filter-mapping>  
        <filter-name>shiroFilter</filter-name>  


        <url-pattern>/*</url-pattern>  
    </filter-mapping> 

通常将这段代码中的filter-mapping放在所有filter-mapping之前,以达到shiro是第一个对web请求进行拦截过滤之目的。这里的fileter-name应该要和第二步中配置的 Java bean的id一致。

第二步,配置各种Java Bean

在root-context.xml文件中配置Shiro


    <?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">  
      
        <!-- Root Context: defines shared resources visible to all other web components -->  
      
        <!-- dataSource -->  
        <bean id="dataSource"  
            class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/etao_java" />  
            <property name="username" value="root" />  
            <property name="password" value="cope9020" />  
        </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="cacheManager" 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="cacheManager"></property>  
        </bean>  
      
        <!--   
           Shiro主过滤器本身功能十分强大,其强大之处就在于它支持任何基于URL路径表达式的、自定义的过滤器的执行  
           Web应用中,Shiro可控制的Web请求必须经过Shiro主过滤器的拦截,Shiro对基于Spring的Web应用提供了完美的支持   
        -->  
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
            <!-- Shiro的核心安全接口,这个属性是必须的 -->  
            <property name="securityManager" ref="securityManager"></property>  
            <!-- 要求登录时的链接(登录页面地址),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 -->  
            <property name="loginUrl" value="/security/login"></property>  
            <!-- 登录成功后要跳转的连接(本例中此属性用不到,因为登录成功后的处理逻辑在LoginController里硬编码) -->  
            <!-- <property name="successUrl" value="/" ></property> -->  
            <!-- 用户访问未对其授权的资源时,所显示的连接 -->  
            <property name="unauthorizedUrl" value="/"></property>  
            <property name="filterChainDefinitions">  
                <value>  
                    /security/*=anon  
                    /tag=authc  
                </value>  
            </property>  
        </bean>  
      
        <!--   
           开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,  
           并在必要时进行安全逻辑验证  
        -->  
        <!--  
        <bean  
            class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>  
        <bean  
            class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">  
            <property name="securityManager" ref="securityManager"></property>  
        </bean>  
        -->  
    </beans>  

上述代码中已经对每个java bean的用途做了详细的注释说明,这里仅对FilterChain过滤链的定义详细阐述一下:

  • 测试用例中对/security/*的访问是不需要认证控制的,这主要是用于用户登录和退出的
  • 测试用例中对/tag的访问是需要认证控制的,就是说只有通过认证的用户才可以访问该资源。如果用户直接在地址栏中访问http://localhost:8880/learning/tag,系统会自动跳转至登录页面,要求用户先进行身份认证。

完成这两步之后,我们可以Run一下程序,如果可以看到以下页面,就表明我们的配置文件没有错误,Shiro和spring MVC的整合已经完成了。后继的步骤可以视为是对整合后的框进行的一个测试




    <%@ page language="java" contentType="text/html; charset=UTF-8"  
        pageEncoding="UTF-8"%>  
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>  
      
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
    <html>  
    <head>  
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
    <title>Login Page</title>  
    </head>  
    <body>  
        <h1>login page</h1>  
        <form id="" action="dologin" method="post">  
            <label>User Name</label> <input tyep="text" name="userName"  
                maxLength="40" /> <label>Password</label><input type="password"  
                name="password" /> <input type="submit" value="login" />  
        </form>  
        <%--用于输入后台返回的验证错误信息 --%>  
        <P><c:out value="${message }" /></P>  
    </body>  
    </html>  

后台登录代码


    /** 
     * 实际的登录代码 
     * 如果登录成功,跳转至首页;登录失败,则将失败信息反馈对用户 
     *  
     * @param request 
     * @param model 
     * @return 
     */  
    @RequestMapping(value = "/dologin")  
    public String doLogin(HttpServletRequest request, Model model) {  
        String msg = "";  
        String userName = request.getParameter("userName");  
        String password = request.getParameter("password");  
        System.out.println(userName);  
        System.out.println(password);  
        UsernamePasswordToken token = new UsernamePasswordToken(userName, password);  
        token.setRememberMe(true);  
        Subject subject = SecurityUtils.getSubject();  
        try {  
            subject.login(token);  
            if (subject.isAuthenticated()) {  
                return "redirect:/";  
            } else {  
                return "login";  
            }  
        } catch (IncorrectCredentialsException e) {  
            msg = "登录密码错误. Password for account " + token.getPrincipal() + " was incorrect.";  
            model.addAttribute("message", msg);  
            System.out.println(msg);  
        } catch (ExcessiveAttemptsException e) {  
            msg = "登录失败次数过多";  
            model.addAttribute("message", msg);  
            System.out.println(msg);  
        } catch (LockedAccountException e) {  
            msg = "帐号已被锁定. The account for username " + token.getPrincipal() + " was locked.";  
            model.addAttribute("message", msg);  
            System.out.println(msg);  
        } catch (DisabledAccountException e) {  
            msg = "帐号已被禁用. The account for username " + token.getPrincipal() + " was disabled.";  
            model.addAttribute("message", msg);  
            System.out.println(msg);  
        } catch (ExpiredCredentialsException e) {  
            msg = "帐号已过期. the account for username " + token.getPrincipal() + "  was expired.";  
            model.addAttribute("message", msg);  
            System.out.println(msg);  
        } catch (UnknownAccountException e) {  
            msg = "帐号不存在. There is no user with username of " + token.getPrincipal();  
            model.addAttribute("message", msg);  
            System.out.println(msg);  
        } catch (UnauthorizedException e) {  
            msg = "您没有得到相应的授权!" + e.getMessage();  
            model.addAttribute("message", msg);  
            System.out.println(msg);  
        }  
        return "login";  
    }  


 登录成功后,会转至首页,并显示出当前用户名。


 登录成功后,会转至首页,并显示出当前用户名。


目录
相关文章
|
4天前
|
设计模式 前端开发 Java
步步深入SpringMvc DispatcherServlet源码掌握springmvc全流程原理
通过对 `DispatcherServlet`源码的深入剖析,我们了解了SpringMVC请求处理的全流程。`DispatcherServlet`作为前端控制器,负责请求的接收和分发,处理器映射和适配负责将请求分派到具体的处理器方法,视图解析器负责生成和渲染视图。理解这些核心组件及其交互原理,有助于开发者更好地使用和扩展SpringMVC框架。
22 4
|
21天前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
64 2
|
2月前
|
JSON 前端开发 Java
SSM:SpringMVC
本文介绍了SpringMVC的依赖配置、请求参数处理、注解开发、JSON处理、拦截器、文件上传下载以及相关注意事项。首先,需要在`pom.xml`中添加必要的依赖,包括Servlet、JSTL、Spring Web MVC等。接着,在`web.xml`中配置DispatcherServlet,并设置Spring MVC的相关配置,如组件扫描、默认Servlet处理器等。然后,通过`@RequestMapping`等注解处理请求参数,使用`@ResponseBody`返回JSON数据。此外,还介绍了如何创建和配置拦截器、文件上传下载的功能,并强调了JSP文件的放置位置,避免404错误。
|
1月前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
45 0
|
2月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
64 2
|
3月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
2月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
175 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
3月前
|
XML 缓存 前端开发
springMVC02,restful风格,请求转发和重定向
文章介绍了RESTful风格的基本概念和特点,并展示了如何使用SpringMVC实现RESTful风格的请求处理。同时,文章还讨论了SpringMVC中的请求转发和重定向的实现方式,并通过具体代码示例进行了说明。
springMVC02,restful风格,请求转发和重定向
|
4月前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
4月前
|
前端开发 应用服务中间件 数据库
SpringMVC入门到实战------八、RESTful案例。SpringMVC+thymeleaf+BootStrap+RestFul实现员工信息的增删改查
这篇文章通过一个具体的项目案例,详细讲解了如何使用SpringMVC、Thymeleaf、Bootstrap以及RESTful风格接口来实现员工信息的增删改查功能。文章提供了项目结构、配置文件、控制器、数据访问对象、实体类和前端页面的完整源码,并展示了实现效果的截图。项目的目的是锻炼使用RESTful风格的接口开发,虽然数据是假数据并未连接数据库,但提供了一个很好的实践机会。文章最后强调了这一章节主要是为了练习RESTful,其他方面暂不考虑。
SpringMVC入门到实战------八、RESTful案例。SpringMVC+thymeleaf+BootStrap+RestFul实现员工信息的增删改查
下一篇
DataWorks