您的位置:首页 > 编程语言 > Java开发

【Shiro + Spring MVC整合】教程

2016-04-09 14:22 537 查看
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() {  
  
    }  
  
    /* 
     * (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界面了

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: