【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、附下源代码地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值