【Shiro + Spring MVC整合】教程——权限控制
1、准备Shiro的架包和spring 的架包
2、项目的架构
3、配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>simpleSpringMCV</display-name> <!-- 加载文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext-shiro.xml </param-value> </context-param> <!-- shiro --> <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>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> <!-- 以.htm结尾的都被mvc拦截 --> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> <!-- 启动spring 加载 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
4、配置applicationContext-shiro.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" 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/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd"> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <property name="successUrl" value="/member/index.htm" /> <property name="loginUrl" value="/login.htm" /> <property name="unauthorizedUrl" value="/error.htm" /> <property name="filters"> <map> <entry key="authc" value-ref="shiro"></entry> </map> </property> <property name="filterChainDefinitions"> <value> /login.htm=anon /submit.htm=anon /error.htm=anon /member/**=authc,roles["member"] </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> --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <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>
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: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/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <mvc:annotation-driven/> <!-- 自动扫描包 --> <context:component-scan base-package="com.cat.spring.controller" /> <!-- mvc返回页面的配置 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 模板路径为WEB-INF/pages/ --> <property name="prefix"> <value>/WEB-INF/pages/</value> </property> <!-- 视图模板后缀为.JSP --> <property name="suffix"> <value>.jsp</value> </property> </bean> </beans>
6、创建ShiroFilter和ShiroRealm
ShiroFilter.java
/** * */ 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 { /* * (non-Javadoc) * * @see javax.servlet.Filter#destroy() */ @Override public void destroy() { // TODO Auto-generated method stub } /* * (non-Javadoc) * * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; Principal principal = httpRequest.getUserPrincipal(); 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("member")); 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); } /* * (non-Javadoc) * * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }
ShiroRealm.java
/** * */ package com.cat.shiro; import java.util.ArrayList; import java.util.List; 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.subject.PrincipalCollection; import com.cat.spring.entity.Role; import com.cat.spring.entity.User; /** * @author chenlf * * 2014-3-24 */ public class ShiroRealm extends AuthorizingRealm { /* * (non-Javadoc) * * @see org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection) */ @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>(); // 简单默认一个用户与角色,实际项目应User user = userService.getByAccount(name); User user = new User("shiro", "123456"); Role role = new Role("member"); user.setRole(role); if (user.getName().equals(name)) { if (user.getRole() != null) { roles.add(user.getRole().getName()); } } else { throw new AuthorizationException(); } SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 增加角色 info.addRoles(roles); return info; } /* * (non-Javadoc) * * @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken) */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authcToken; // 简单默认一个用户,实际项目应User user = userService.getByAccount(token.getUsername()); User user = new User("shiro", "123456"); if (user == null) { throw new AuthorizationException(); } SimpleAuthenticationInfo info = null; if (user.getName().equals(token.getUsername())) { info = new SimpleAuthenticationInfo(user.getName(), user.getPassword(), getName()); } return info; } }
7、配置对应的Controller文件
LoginController.java
/** * */ 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; /** * @author chenlf * * 2014-3-24 */ @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("member")); 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.htm"); } }IndexController.java
/** * */ 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; } }
8、对应的jsp 就不写了
9、来看看效果图吧
没有登陆状态的访问/member/**被shiro拦截到登入界面
当用户(角色为member)为shiro 密码为123456时 再次登入/member/index.htm时就不会跳转到login界面了
10、附下源代码地址
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。