1 Shiro的授权

1.1 授权流程

1.2 授权方式

  • shiro支持三种方式的授权

1.2.1 编程式

  • 通过编写if/else完成授权代码。
if(subject.hasRole("role1")){
//有权限
}else{
//没有权限
}

1.2.2 注解式

  • 通过在执行的Java方法上配置相应的注解完成。
@RequiresRoles("")
public void hello(){
//有权限
}

1.2.3 JSP标签

  • 在JSP标签页面通过相应的标签完成。
<shiro:hasRole name="admin">
<!-- 有权限 -->
</shiro:hasRole>

1.3 授权测试

1.3.1 shiro-permissioin.ini

  • 创建存放权限的配置文件shiro-permission.ini,如下:
[users]
# 用户zhangsan的密码是123456,此用户具有role1和role2两个角色
zhangsan=123456,role1,role2
lisi=123456,role1 [roles]
# role1对资源user具有create、update权限
role1=user:create,user:update
# role2对资源user具有create、delete权限
role2=user:create,user:delete
# role3对资源user具有create权限
role3=user:create

1.3.2 权限字符串规则

  • 权限字符串的规则是“资源标识符:操作:资源实例标识符”,意思是对那个资源的那个实例具有什么的操作,“:”是资源、操作、实例的分隔符,权限字符串也可以使用*通配符。
  • 比如:
用户创建权限:user:create或user:create:*
用户修改实例001的权限:user:update:001
用户实例001的所有权限:user:*:001

1.3.3 测试代码

  • 授权需要在用户认证完毕之后,方可进行授权。

1.3.3.1 基于角色的授权

  • 示例:
package com.sunxiaping.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test; import java.util.Arrays; public class ShiroTest { @Test
public void test() {
//创建SecurityManager工厂对象:加载配置文件,创建工厂对象
Factory<SecurityManager> securityManagerFactory = new IniSecurityManagerFactory("classpath:shiro-permission.ini");
//获取SecurityManager对象
SecurityManager securityManager = securityManagerFactory.getInstance();
//将SecurityManager对象绑定到当前运行环境中,让系统随时随地都可以访问SecurityManager对象
SecurityUtils.setSecurityManager(securityManager);
//获取Subject主体对象
Subject subject = SecurityUtils.getSubject();
//执行登录
try {
subject.login(new UsernamePasswordToken("zhangsan", "123456"));
} catch (UnknownAccountException e) {
System.out.println("用户名不存在");
e.printStackTrace();
} catch (IncorrectCredentialsException e) {
System.out.println("用户名存在,密码不正确");
e.printStackTrace();
}
//判断当前用户是否拥有某个角色,返回true表示拥有,返回false表示没有
System.out.println(subject.hasRole("role1"));
//判断当前用户是否拥有一些角色,返回true表示全部拥有,返回false表示不全部拥有
System.out.println(subject.hasAllRoles(Arrays.asList("role1", "role2", "role3")));
//判断当前用户是否拥有一些角色,返回值是boolean[],如果有角色,那么数组中对应的就是true,如果没有数组中对应的就是false
System.out.println(Arrays.toString(subject.hasRoles(Arrays.asList("role1", "role2", "role3")))); //检查当前用户是否拥有某个角色,如果有,不做任何操作,没有报异常
subject.checkRole("role1");
//检查当前用户是否拥有某些角色,如果传入的角色当前用户没有,就会报异常
subject.checkRoles("role1","role2","role3"); }
}

1.3.3.2 基于资源的授权

  • 示例:
package com.sunxiaping.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test; import java.util.Arrays; public class ShiroTest { @Test
public void test() {
//创建SecurityManager工厂对象:加载配置文件,创建工厂对象
Factory<SecurityManager> securityManagerFactory = new IniSecurityManagerFactory("classpath:shiro-permission.ini");
//获取SecurityManager对象
SecurityManager securityManager = securityManagerFactory.getInstance();
//将SecurityManager对象绑定到当前运行环境中,让系统随时随地都可以访问SecurityManager对象
SecurityUtils.setSecurityManager(securityManager);
//获取Subject主体对象
Subject subject = SecurityUtils.getSubject();
//执行登录
try {
subject.login(new UsernamePasswordToken("zhangsan", "123456"));
} catch (UnknownAccountException e) {
System.out.println("用户名不存在");
e.printStackTrace();
} catch (IncorrectCredentialsException e) {
System.out.println("用户名存在,密码不正确");
e.printStackTrace();
}
//判断当前用户是否拥有某个权限,返回true表示有权限,反之,则返回false
System.out.println(subject.isPermitted("user:create"));
//判断当前用户是否拥有一些权限,返回true表示全部拥有,返回false表示不全部拥有
System.out.println(subject.isPermittedAll("user:create", "user:view"));
//判断当前用户是否拥有一些权限,返回boolean数组,true表示有,false表示没有
System.out.println(Arrays.toString(subject.isPermitted("user:create", "user:view")));
//校验当前用户是否具有某个权限,有,无操作,没有,将抛出异常
subject.checkPermission("user:create");
//校验当前用户是否具有某些权限,有,无操作,没有,将抛出异常
subject.checkPermissions("user:create", "user:view");
} }

1.4 自定义Realm

  • 和自定义认证Realm一样,大部分情况是要从数据库获取权限数据,这里直接实现的是基于资源的授权。

1.4.1 Realm的代码

  • 示例:
package com.sunxiaping.shiro;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection; import java.util.ArrayList;
import java.util.List; /**
* 自定义Realm
*/
public class CustomRealm extends AuthorizingRealm { @Override
public String getName() {
return "customRealm";
} /**
* 授权
*
* @param principals 用户认证的身份信息,其实就是doGetAuthenticationInfo返回值的第一个参数,本例是是username
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) principals.getPrimaryPrincipal(); //根据用户名查询用户制定的角色和权限
//假设用户在数据库中具有role1角色
List<String> roles = new ArrayList<>();
roles.add("role1");
//假设用户在数据库中拥有user:delete权限
List<String> permissions = new ArrayList<>();
permissions.add("user:delete"); //返回用户在数据库中的权限和角色
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRoles(roles);
info.addStringPermissions(permissions);
return info;
} /**
* 认证
*
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取身份信息 zhangsan
Object principal = token.getPrincipal(); //假设从数据库中查询到的zhangsan的密码是123456 String password = "123456"; AuthenticationInfo info = new SimpleAuthenticationInfo(principal, password, getName()); return info;
}
}

1.4.2 shiro-realm.ini

[main]
# 自定义Realm
customRealm = com.sunxiaping.shiro.CustomRealm
# 将Realm设置到SecurityManager中
securityManager.realms=$customRealm

1.4.3 测试

  • 示例:
package com.sunxiaping.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test; public class ShiroTest { @Test
public void test() {
//创建SecurityManager工厂对象:加载配置文件,创建工厂对象
Factory<SecurityManager> securityManagerFactory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
//获取SecurityManager对象
SecurityManager securityManager = securityManagerFactory.getInstance();
//将SecurityManager对象绑定到当前运行环境中,让系统随时随地都可以访问SecurityManager对象
SecurityUtils.setSecurityManager(securityManager);
//获取Subject主体对象
Subject subject = SecurityUtils.getSubject();
//执行登录
try {
subject.login(new UsernamePasswordToken("zhangsan", "123456"));
} catch (UnknownAccountException e) {
System.out.println("用户名不存在");
e.printStackTrace();
} catch (IncorrectCredentialsException e) {
System.out.println("用户名存在,密码不正确");
e.printStackTrace();
} System.out.println(subject.isPermitted("user:delete"));
System.out.println(subject.hasRole("role1")); } }

2 web集成

2.1 集成原理

  • shiro和web集成,主要是通过配置一个ShiroFilter拦截所有的URL,其中ShiroFilter类似于如Struts2和SpringMVC这种web框架的前端控制器,是所有请求的入口点,负责根据配置(如ini配置文件),判断请求进入URL是否需要登录/权限等工作。

2.2 web集成

2.2.1 添加相关依赖

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<!-- shiro核心的依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<!-- shiro对web支持的依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.2</version>
</dependency>
<!-- serlvet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>

2.2.2 配置web.xml

<?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"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <!--初始化securityManager对象所需要的环境配置-->
<context-param>
<param-name>shiroEnvironmentClass</param-name>
<param-value>org.apache.shiro.web.env.IniWebEnvironment</param-value>
</context-param>
<context-param>
<param-name>shiroConfigLocations</param-name>
<param-value>classpath:shiro.ini</param-value>
</context-param>
<!--
从Shiro 1.2开始引入了Environment/WebEnvironment的概念,即由它们的实现提供相应的SecurityManager及其相应的依赖。
ShiroFilter会自动找到Environment然后获取相应的依赖。
底层:返回反射创建shiroEnvironmentClass对象,调用其init方法.
shiroEnvironmentClass中的init方法创建SecurityManager实例并绑定到当前运行环境
-->
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener> <filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<!-- 拦截所有的请求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

2.2.3 shiro.ini

[main]
#默认是/login.jsp
authc.loginUrl = /login
#用户无需要的角色跳转的页面
roles.unauthorizedUrl = /nopermission.jsp
#用户无需要的权限时提哦啊转的页面
perms.unauthorizedUrl=/nopermission.jsp
#登出之后重定向的页面
logout.redirectUrl=/login
[users]
admin=123456,admin
sunxiaping=123456,deptMgr
[roles]
admin=employee"*,department:*
deptMgr=department:view
[urls]
#静态资源可以匿名
/static/**=anon
#访问员工列表需要身份认证以及需要有admin角色
/emplouee=authc,roles[admin]
#访问部门列表需要身份认证以及需要拥有department:view的权限
/department=authc,perms["department:view"]
#当请求logout,会被logout捕获并清楚session
/logout=logout
#所有的请求都需要身份认证
/**=authc

2.2.4 Shiro默认的过滤器

  • anno:匿名拦截器,即不需要登录即可访问;一般用于静态资源过滤。例如:/static/**=anno
  • authc:表示需要认证(登录)才能使用。例如:/**=auth,其主要属性如下:
    • usernameParam:表单提交的用户名参数名(username)。
    • passwordParam:表单提交的密码参数名(password)。
    • rememberMeParam:记住我参数名(rememberMe)。
    • logurl:登录页面地址。  
  • authcBasic:BasicHttp身份验证拦截器。其主要属性如下:
    • applicationName:弹出登录框显示的信息(application)。      
  • roles:角色授权拦截器,验证用户是否拥有资源角色。例如:/admin/**=roles[admin]
  • perms:权限授权拦截器,验证用户是否拥有资源权限。例如:/user/create=perms["user:create"]
  • user:用户拦截器,用户已经身份认证/记住我登录都可。例如:/index=user
  • logout:退出拦截器,例如:/logout=logout,其主要属性如下:
    • redirectUrl:退出成功后重定向的地址(/)  
  • port:端口拦截器,例如:/test=port[80],如果用户访问该页面是非80,将自动将请求端口改为80并重定向到该80端口,其他路径/参数等都一样,其主要属性如下:
    • port(80):可以通过的端口。  
  • rest:rest风格拦截器,自动根据请求方法构建权限字符串(GET=read,POST=create,PUT=update,DELETE=delete,HEAD=read,TRACE=read,OPTIONS=read,MKCOL=create)构建权限字符串。例如:/users=rest[user],会自动拼出“user:create,user:create,user:update,user:delete”权限字符串进行权限匹配(所有权限都会匹配)。
  • ssl:SSL拦截器,只有请求协议是https才会通过,否则自动跳转到https端口(443),其他和port拦截器一样。

2.2.4.1 authc登录拦截器工作原理

  • authc登录拦截器有2个作用:
  • ①登录认证:请求进来的时候,拦截并判断当前用户是否登录了,如果已经登录了就放行,如果没有登录,则跳转到authc.loginUrl属性配置的路径。注意:默认是/login.jsp。
  • ②执行登录认证:请求进来的时候,如果请求的路径为authc.loginUrl属性配置的路径(如果没有配置,默认是/login.jsp),如果当前用户没有登录,authc这个拦截器会尝试获取请求中的账号和密码值,然后比对ini配置文件或者realm中的用户列表,如果比对正确,直接执行登录操作,反之,抛异常,跳转到authc.loginUrl指定的路径。注意:请求中的账号和密码必须固定为username和password,如果需要改动需要额外指定,authc.usernameParam=xxx,authc.passwordParam=xxx。

2.2.4.2 authc登录成功后处理逻辑

2.2.4.3 authc登录失败后处理逻辑

  • 登录失败之后,会将异常信息写入到shiroLoginFailure的request域中,其值是异常类的全限定名。

2.2.5 shiro的jsp标签

  • 步骤:
  • ①在jsp中引入shiro的标签库
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
  • ②标签是否拥有权限进而显示操作按钮
<shiro:hasPermission name="employee:add">
<a href="${pageContext.request.contextPath}/employee?cmd=input">新增</a>
</shiro:hasPermission>
  • ③显示当前的登录用户
<shiro:principal></shiro:principal>

2.2.6 登出

  • 只需要在shiro.ini中配置一下即可。
#当请求loginOut,会被logout捕获并清除session
/loginOut=logout
  • 示例:
<a href="${pageContext.request.contextPath}/loginOut">退出</a>

3 Spring集成

3.1 准备工作

3.1.1 sql文件

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for permission
-- ----------------------------
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`resource` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of permission
-- ---------------------------- -- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`sn` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('', '部门经理', 'deptMgr');
INSERT INTO `role` VALUES ('', '员工经理', 'empMgr'); -- ----------------------------
-- Table structure for role_permission
-- ----------------------------
DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission` (
`role_id` bigint(20) NOT NULL,
`permission_id` bigint(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of role_permission
-- ---------------------------- -- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('', 'admin', '');
INSERT INTO `user` VALUES ('', 'zhangsan', ''); -- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
`user_id` bigint(20) NOT NULL,
`role_id` bigint(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of user_role
-- ----------------------------

3.1.2 新建jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///shiro?createDatabaseIfNotExist=true&amp;useUnicode=true&amp;characterEncoding=UTF-8
jdbc.username=root
jdbc.password=

3.1.3 log4j.properties

# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.cn.wolfcode.shiro=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

3.1.4 spring.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" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--1:引入数据源配置文件-->
<context:property-placeholder location="classpath:jdbc.properties" system-properties-mode="NEVER"/>
<!--2:配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/> </bean> </beans>

3.1.5 mvc.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" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--1:配置DI注解解析器-->
<context:annotation-config/>
<!--2:配置IoC注解解析器-->
<context:component-scan base-package="cn.wolfcode.shiro"/>
<!--3:配置mvc注解解析器-->
<mvc:annotation-driven/>
<!--4:静态资源处理-->
<mvc:default-servlet-handler/> <!--5:配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--6:引入shiro配置文件--> <!--7:引入spring配置文件-->
<import resource="classpath:spring.xml"></import>
</beans>

3.1.6 web.xml

<?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"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>Archetype Created Web Application</display-name> <servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <!--编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter> <filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> </web-app>

3.2 添加Shiro和Spring集成依赖的jar包

  • 完整项目的jar包的maven坐标:
        <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
</dependency> <!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency> <!--spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${org.springframework.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version}</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency> <!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.14</version>
</dependency> <!-- aspectj -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.4</version>
</dependency> <dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency> <!-- cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency> <!--日志-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency> <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency> <!-- jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency> <!--shiro-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.8</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.2</version>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-quartz</artifactId>
<version>1.2.2</version>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.2</version>
</dependency>
  • 其中Shiro和Spring整合的jar包的maven坐标是:
        <dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.8</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.2</version>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-quartz</artifactId>
<version>1.2.2</version>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.2</version>
</dependency>

3.3 配置web.xml

  • 完整配置:
<?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"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>Archetype Created Web Application</display-name> <servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <!--编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter> <filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- 配置Spring和Shiro集成需要的ShiroFilter代理类,DelegatingFilterProx会从spring容器中找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> </web-app>
  • 其中,配置Spring和Shiro集成需要的ShiroFilter代理类,DelegatingFilterProxy会总Spring容器中找ShiroFilter
<!--
配置Spring和Shiro集成需要的ShiroFilter代理类,DelegatingFilterProxy会从spring容器中找shiroFilter
注意:<filter-name>必须和shiro配置文件中的真实ShiroFilter Bean的id一致
-->
<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>

3.3 添加shiro的配置文件

  • 新建spring-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" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--配置自定义的realm-->
<bean id="userRealm" class="cn.wolfcode.shiro.realm.UserRealm"> </bean> <!-- 配置安全管理器SecurityManager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="userRealm"/> </bean> <!-- 定义ShiroFilter -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login"/>
<property name="unauthorizedUrl" value="/nopermission.jsp"/>
<property name="filterChainDefinitions">
<value>
/logout=logout
/**=authc
</value>
</property>
</bean> </beans>
  • 在mvc.xml中将shiro的配置文件加入进去:
<import resource="classpath:spring-shiro.xml"></import>
<?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:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--1:配置DI注解解析器-->
<context:annotation-config/>
<!--2:配置IoC注解解析器-->
<context:component-scan base-package="cn.wolfcode.shiro"/>
<!--3:配置mvc注解解析器-->
<mvc:annotation-driven/>
<!--4:静态资源处理-->
<mvc:default-servlet-handler/> <!--5:配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--6:引入shiro配置文件-->
<import resource="classpath:spring-shiro.xml"></import> <!--7:引入spring配置文件-->
<import resource="classpath:spring.xml"></import>
</beans>

3.4 测试

  • 访问地址:http://localhost:8080/main

最新文章

  1. PHP代码获取客户端IP地址经纬度及所在城市
  2. linux svn 提交文件时强制填写备注
  3. ActionBarSherlock环境搭建
  4. js 如何在浏览器中获取当前位置的经纬度
  5. exp/imp使用
  6. OD: Peimei &amp; Versioning Analysis
  7. 在birt中解决引用了不存在的绑定出现的问题
  8. Asp.Net--回调技术
  9. join 数据库
  10. vs2012快速将项目托管到github
  11. Python3数据库模块(sqlite3,SQLite3)
  12. hdu4605 树状数组+离散化+dfs
  13. 如何设置静态IP
  14. 【ODI】| 数据ETL:从零开始使用Oracle ODI完成数据集成(三)
  15. sqlserver2016新功能
  16. Android应用开发-网络编程(一)
  17. 使用SecureCRT软件运维的配置习惯
  18. FastReport报表设计(仔细看)
  19. 初始化android studio的方法
  20. (实用)Eclipse中使用命令行(运行外部程序)

热门文章

  1. linux(centOS7)的基本操作(七) 其它
  2. asp.net mvc 依赖注入Ninject
  3. 彻底搞懂snowflake算法及百度美团的最佳实践
  4. Windows客户端 Linux服务器通讯 字符编码问题
  5. java中抽象类、接口及区别
  6. tableau日常管理
  7. 【转】mysql用sql实现split函数
  8. ubuntu 个人常用命令
  9. 通过sohu获取浏览器端IP地址
  10. [Vue] vue的一些面试题