SpringMvc 集成 shiro 实现权限角色管理-maven

1、项目清单展示

2、项目源码解析

1)spring-context.xml ------spring 父上下文

<?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:context="http://www.springframework.org/schema/context"

xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/mvc

http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.1.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

<context:annotation-config />

<!-- 默认扫描的包路径 -->

<context:component-scan base-package="com" />

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">

<property name="securityManager" ref="securityManager" />

<property name="successUrl" value="/member/loginsuccess.jsp" />

<property name="loginUrl" value="/login.jsp" />

<property name="unauthorizedUrl" value="/error.html" />

<property name="filters">

<map>

<entry key="authc" value-ref="shiro"></entry>

</map>

</property>

<!-- 下面value值的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()的值来的 -->

<!-- anon:它对应的过滤器里面是空的,什么都没做,这里.do和.jsp后面的*表示参数,比方说login.jsp?main这种 -->

<!-- authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter -->

<property name="filterChainDefinitions">

<value>

/login.jsp=anon

/member/loginsuccess.jsp=anon

/error.html=authc

/member/**=authc,roles["edit"]

/edit=authc,roles["edit"],perms["delete1"]

/getJson/**=anon

</value>

</property>

</bean>

<bean id="shiro" class="com.cat.shiro.ShiroFilter">

</bean>

<bean id="shiroRealm" class="com.cat.shiro.ShiroRealm" />

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

<property name="realm" ref="shiroRealm" />

<!-- 需要使用cache的话加上这句 <property name="cacheManager" ref="shiroEhcacheManager"

/> -->

</bean>

<!-- 用户授权信息Cache, 采用EhCache,需要的话就配置上此信息 <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">

<property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"

/> </bean> -->

<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

<!-- 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证 -->

<!-- 配置以下两个bean即可实现此功能 -->

<!-- Enable Shiro Annotations for Spring-configured beans. Only run after

the lifecycleBeanProcessor has run -->

<!-- 由于本例中并未使用Shiro注解,故注释掉这两个bean(个人觉得将权限通过注解的方式硬编码在程序中,查看起来不是很方便,没必要使用) -->

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

2)dispatcher-servlet.xml---------springMvc 配置文件

<?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: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.0.xsd

http://www.springframework.org/schema/mvc

http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd"

default-lazy-init="true">

<!-- 添加注解驱动 -->

<context:annotation-config />

<mvc:annotation-driven />

<!-- 默认扫描的包路径 -->

<context:component-scan base-package="com" />

<mvc:default-servlet-handler/>

<!-- mvc返回页面的配置 -->

<bean id="viewResolver"

class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<!-- 模板路径为WEB-INF/pages/ -->

<property name="prefix">

<value>/WEB-INF/</value>

</property>

<!-- 视图模板后缀为.JSP -->

<property name="suffix">

<value>.jsp</value>

</property>

</bean>

</beans>

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"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"

version="3.0">

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>

classpath:spring-context.xml

</param-value>

</context-param>

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

<filter-name>encodingFilter</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>encodingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<servlet>

<servlet-name>dispatcher</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>dispatcher</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

</web-app>

4)顺序源码

package com.cat.shiro;

import java.io.IOException;

import java.security.Principal;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;

import org.apache.shiro.authc.UsernamePasswordToken;

import org.apache.shiro.subject.Subject;

import com.cat.spring.entity.Role;

import com.cat.spring.entity.User;

/**

* @author chenlf

*

* 2014-3-24

*/

public class ShiroFilter implements Filter {

@Override

public void destroy() {

}

@Override

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

System.out.println("启用filter........");

HttpServletRequest httpRequest = (HttpServletRequest) request;

HttpServletResponse httpResponse = (HttpServletResponse) response;

Principal principal = httpRequest.getUserPrincipal();

System.out.println(principal);

System.out.println("getUserPrincipal is :" + principal);

if (principal != null) {

Subject subjects = SecurityUtils.getSubject();

// 为了简单,这里初始化一个用户。实际项目项目中应该去数据库里通过名字取用户:

// 例如:User user = userService.getByAccount(principal.getName());

User user = new User();

user.setName("shiro");

user.setPassword("123456");

user.setRole(new Role("edit"));

if (user.getName().equals(principal.getName())) {

UsernamePasswordToken token = new UsernamePasswordToken(

user.getName(), user.getPassword());

subjects = SecurityUtils.getSubject();

subjects.login(token);

subjects.getSession();

} else {

// 如果用户为空,则subjects信息登出

if (subjects != null) {

subjects.logout();

}

}

}

chain.doFilter(httpRequest, httpResponse);

}

@Override

public void init(FilterConfig arg0) throws ServletException {

}

}

package com.cat.shiro;

import java.util.ArrayList;

import java.util.List;

import org.apache.shiro.SecurityUtils;

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.authc.UsernamePasswordToken;

import org.apache.shiro.authz.AuthorizationException;

import org.apache.shiro.authz.AuthorizationInfo;

import org.apache.shiro.authz.SimpleAuthorizationInfo;

import org.apache.shiro.realm.AuthorizingRealm;

import org.apache.shiro.session.Session;

import org.apache.shiro.subject.PrincipalCollection;

import org.apache.shiro.subject.Subject;

import com.cat.spring.entity.Role;

import com.cat.spring.entity.User;

import com.cat.spring.service.UserService;

/**

* 该类从principals中取得用户名称进行匹配,在principals中默认保存了当前登陆人的用户名称,从而将该用户的角色加入到作用域中;

*/

public class ShiroRealm extends AuthorizingRealm {

//登陆第二步,通过用户信息将其权限和角色加入作用域中,达到验证的功能

@Override

protected AuthorizationInfo doGetAuthorizationInfo(

PrincipalCollection principals) {

// 根据用户配置用户与权限

if (principals == null) {

throw new AuthorizationException(

"PrincipalCollection method argument cannot be null.");

}

String name = (String) getAvailablePrincipal(principals);

List<String> roles = new ArrayList<String>();

List<String> permissions = new ArrayList<String>();

// 通过当前登陆用户的姓名查找到相应的用户的所有信息

User user = UserService.getUserByName(name);

Role role = user.getRole();

if (user.getName().equals(name)) {

if (user.getRole() != null) {

// 装配用户的角色和权限 delete

roles.add(user.getRole().getName());

permissions.add("delete");

}

} else {

throw new AuthorizationException();

}

SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

// 为用户设置角色和权限

info.addRoles(roles);

info.addStringPermissions(permissions);

return info;

}

/**

* 验证当前登录的Subject

* @see 经测试:本例中该方法的调用时机为LoginController.login()方法中执行Subject.login()时

*/

@SuppressWarnings("unused")

@Override

protected AuthenticationInfo doGetAuthenticationInfo(

AuthenticationToken authcToken) throws AuthenticationException {

// 登陆后的操作,此处为登陆有的第一步操作,从LoginController.login中调用了此处的token

UsernamePasswordToken token = (UsernamePasswordToken) authcToken;

System.out.println("token is :" + token);

// 简单默认一个用户,实际项目应User user = userService.getByAccount(token.getUsername());

// 下面通过读取token中的数据重新封装了一个user

String pwd = new String(token.getPassword());

User user = new User(token.getUsername(), pwd);

if (user == null) {

throw new AuthorizationException();

}

SimpleAuthenticationInfo info = null;

if (user.getName().equals(token.getUsername())) {

info = new SimpleAuthenticationInfo(user.getName(),

user.getPassword(), getName());

}

//将该User村放入session作用域中

//this.setSession("user", user);

return info;

}

/**

* 将一些数据放到ShiroSession中,以便于其它地方使用

* 比如Controller,使用时直接用HttpSession.getAttribute(key)就可以取到

*/

@SuppressWarnings("unused")

private void setSession(Object key, Object value) {

Subject currentUser = SecurityUtils.getSubject();

if (null != currentUser) {

Session session = currentUser.getSession();

System.out

.println("Session默认超时时间为[" + session.getTimeout() + "]毫秒");

if (null != session) {

session.setAttribute(key, value);

}

}

}

}

/**

*

*/

package com.cat.spring.controller;

import org.apache.shiro.SecurityUtils;

import org.apache.shiro.authc.UsernamePasswordToken;

import org.apache.shiro.subject.Subject;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.servlet.ModelAndView;

import com.cat.spring.entity.Role;

import com.cat.spring.entity.User;

@Controller

public class LoginController {

@RequestMapping(value = "/login", method = RequestMethod.GET)

public ModelAndView login() {

return new ModelAndView("/login");

}

/**

* 处理登陆配置

*/

@RequestMapping(value = "/submit", method = RequestMethod.POST)

public ModelAndView submit(String username, String password) {

User user = new User("shiro", "123456");

user.setRole(new Role("edit"));

try {

// 如果登陆成功

if (user.getName().equals(username) && user.getPassword().equals(password)) {

UsernamePasswordToken token = new UsernamePasswordToken(user.getName(), user

.getPassword().toString());

Subject subject = SecurityUtils.getSubject();

subject.login(token);

}

} catch (Exception e) {

e.printStackTrace();

}

return new ModelAndView("redirect:/member/index.jsp");

}

}

/**

* 该类没什么用处,还要研究

*/

package com.cat.spring.controller.member;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.servlet.ModelAndView;

/**

* @author chenlf

*

* 2014-3-24

*/

@Controller

@RequestMapping(value = "/member")

//会员中心要被拦截

public class IndexController {

// 拦截/index.htm 方法为GET的请求

@RequestMapping(value = "/index", method = RequestMethod.GET)

public ModelAndView index() {

ModelAndView view = new ModelAndView();

view.setViewName("/member/index");

return view;

}

}

package com.cat.spring.entity;

public class Role {

private String name;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Role() {

// TODO Auto-generated constructor stub

}

public Role(String name) {

this.name = name;

}

}

package com.cat.spring.entity;

public class User {

private String name;

private String password;

private Role role;

public Role getRole() {

return role;

}

public void setRole(Role role) {

this.role = role;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public User() {

// TODO Auto-generated constructor stub

}

public User(String name, String password) {

this.name = name;

this.password = password;

}

}

package com.cat.spring.service;

import org.springframework.stereotype.Repository;

import com.cat.spring.entity.Role;

import com.cat.spring.entity.User;

@Repository

public class UserService {

public static User getUserByName(String name){

//通过姓名从数据库中读取到相应的用户

User user = new User(name, "123456");

user.setRole(new Role("edit"));

return user;

}

}

package com.lives.shiro.controller;

import org.apache.shiro.authz.annotation.RequiresRoles;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

public class HelloController {

@RequestMapping("/getJson")

public String getJson() {

System.out.println("进入colloer");

return "success";

}

@RequestMapping("/edit")

public String hello2() {

return "redirect:/member/index.jsp";

}

}

3、pox.xml-maven管理

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.lives</groupId>

<artifactId>lives_shiro</artifactId>

<packaging>war</packaging>

<version>0.0.1-SNAPSHOT</version>

<name>lives_shiro Maven Webapp</name>

<url>http://maven.apache.org</url>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<spring.version>3.1.1.RELEASE</spring.version>

</properties>

<dependencies>

<!-- spring begin -->

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-webmvc</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-jdbc</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-aop</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-test</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-core</artifactId>

<version>2.4.1</version>

</dependency>

<dependency>

<groupId>org.codehaus.jackson</groupId>

<artifactId>jackson-core-asl</artifactId>

<version>1.9.13</version>

</dependency>

<dependency>

<groupId>javax.ws.rs</groupId>

<artifactId>javax.ws.rs-api</artifactId>

<version>2.0</version>

</dependency>

<dependency>

<groupId>org.codehaus.jackson</groupId>

<artifactId>jackson-mapper-asl</artifactId>

<version>1.9.13</version>

</dependency>

<dependency>

<groupId>org.aspectj</groupId>

<artifactId>aspectjweaver</artifactId>

<version>1.7.3</version>

</dependency>

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>jstl</artifactId>

<version>1.2</version>

</dependency>

<dependency>

<groupId>taglibs</groupId>

<artifactId>standard</artifactId>

<version>1.1.2</version>

</dependency>

<!-- spring end -->

<!-- servlet -->

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>servlet-api</artifactId>

<version>3.0-alpha-1</version>

</dependency>

<!-- mybatis begin -->

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis</artifactId>

<version>3.2.2</version>

</dependency>

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis-spring</artifactId>

<version>1.2.0</version>

</dependency>

<!-- mybatis end -->

<!-- log4j -->

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>1.7.5</version>

</dependency>

<!-- httpclient begin -->

<dependency>

<groupId>org.apache.httpcomponents</groupId>

<artifactId>httpclient</artifactId>

<version>4.3.4</version>

</dependency>

<dependency>

<groupId>org.apache.httpcomponents</groupId>

<artifactId>httpasyncclient</artifactId>

<version>4.0.2</version>

</dependency>

<dependency>

<groupId>commons-httpclient</groupId>

<artifactId>commons-httpclient</artifactId>

<version>3.1</version>

</dependency>

<!-- httpclient end -->

<!-- springmvc rabbitmq -->

<dependency>

<groupId>com.rabbitmq</groupId>

<artifactId>amqp-client</artifactId>

<version>3.3.0</version>

</dependency>

<dependency>

<groupId>org.springframework.amqp</groupId>

<artifactId>spring-amqp</artifactId>

<version>1.3.0.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework.amqp</groupId>

<artifactId>spring-rabbit</artifactId>

<version>1.3.0.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework.retry</groupId>

<artifactId>spring-retry</artifactId>

<version>1.0.3.RELEASE</version>

</dependency>

<!--json-lib -->

<dependency>

<groupId>net.sf.json-lib</groupId>

<artifactId>json-lib</artifactId>

<version>2.4</version>

<classifier>jdk15</classifier>

</dependency>

<!-- springmvc redis -->

<dependency>

<groupId>org.springframework.data</groupId>

<artifactId>spring-data-redis</artifactId>

<version>1.3.2.RELEASE</version>

</dependency>

<dependency>

<groupId>redis.clients</groupId>

<artifactId>jedis</artifactId>

<version>2.4.2</version>

</dependency>

<!-- 汉语拼音包 -->

<dependency>

<groupId>com.belerweb</groupId>

<artifactId>pinyin4j</artifactId>

<version>2.5.0</version>

</dependency>

<!-- 阿里 德鲁伊连接池 -->

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid</artifactId>

<version>1.0.5</version>

</dependency>

<!-- mysql -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.30</version>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>3.8.1</version>

<scope>test</scope>

</dependency>

<!-- shiro 使用maven -->

<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>org.apache.shiro</groupId>

<artifactId>shiro-spring</artifactId>

<version>1.2.2</version>

</dependency>

<dependency>

<groupId>cglib</groupId>

<artifactId>cglib</artifactId>

<version>2.2.2</version>

</dependency>

</dependencies>

<profiles>

<profile>

<id>dev</id>

<properties>

<package.environment>dev</package.environment>

</properties>

<activation>

<activeByDefault>true</activeByDefault>

</activation>

</profile>

<profile>

<id>test</id>

<properties>

<package.environment>test</package.environment>

</properties>

</profile>

<profile>

<id>prod</id>

<properties>

<package.environment>prod</package.environment>

</properties>

</profile>

</profiles>

<build>

<finalName>lives_shiro</finalName>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.1</version>

<configuration>

<source>1.8</source>

<target>1.8</target>

<archive>

<addMavenDescriptor>false</addMavenDescriptor>

</archive>

<webResources>

<resource>

<directory>src/main/resources/properties/${package.environment}</directory>

<targetPath>WEB-INF/classes</targetPath>

<filtering>true</filtering>

</resource>

</webResources>

</configuration>

</plugin>

</plugins>

</build>

</project>

4、filterChainDefinitions配置讲解

http://www.cppblog.com/guojingjia2006/archive/2014/05/14/206956.html

5、项目中webapp目录的下载

http://download.csdn.net/detail/u014201191/8767629

SpringMvc 集成 shiro 实现权限角色管理-maven

相关推荐