shiro整合springmvc

来源:互联网 发布:centos jdk1.7 安装 编辑:程序博客网 时间:2024/05/17 04:42

代码:https://github.com/jxq0816/springmvc_framework

参考:http://shiro.apache.org/spring.html

一、pom.xml 加入shiro的dependency

<!-- SECURITY begin -->    <dependency>      <groupId>org.apache.shiro</groupId>      <artifactId>shiro-core</artifactId>      <version>${shiro.version}</version>    </dependency>    <dependency>      <groupId>org.apache.shiro</groupId>      <artifactId>shiro-spring</artifactId>      <version>${shiro.version}</version>    </dependency>    <dependency>      <groupId>org.apache.shiro</groupId>      <artifactId>shiro-cas</artifactId>      <version>${shiro.version}</version>      <exclusions>        <exclusion>          <groupId>commons-logging</groupId>          <artifactId>commons-logging</artifactId>        </exclusion>      </exclusions>    </dependency>    <dependency>      <groupId>org.apache.shiro</groupId>      <artifactId>shiro-web</artifactId>      <version>${shiro.version}</version>    </dependency>    <dependency>      <groupId>org.apache.shiro</groupId>      <artifactId>shiro-ehcache</artifactId>      <version>${shiro.version}</version>    </dependency>    <!-- SECURITY end -->

二、web.xml 配置shiro过滤器

 <context-param>        <param-name>contextConfigLocation</param-name>        <param-value>            classpath:/spring-context.xml            classpath:/spring-context-shiro.xml        </param-value>    </context-param><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>

三、resources目录下新建spring-context-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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd"default-lazy-init="true"><description>Shiro Configuration</description><!-- Shiro权限过滤过滤器定义 --><bean name="shiroFilterChainDefinitions" class="java.lang.String"><constructor-arg><value>/user/login = anon/user/logout = anon/** = authc</value></constructor-arg></bean><!-- 安全认证过滤器 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager" /><property name="loginUrl" value="/user/login" /><property name="successUrl" value="/user/login" /><property name="filterChainDefinitions"><ref bean="shiroFilterChainDefinitions"/></property></bean><!-- 继承自AuthorizingRealm的自定义Realm,即指定Shiro验证用户登录的类为自定义的MyRealm.java --><bean id="myRealm" class="com.week7i.share.security.SystemAuthorizingRealm"/><!-- 定义Shiro安全管理配置 --><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm" ref="myRealm" /></bean></beans>
四、spring-mvc-dispatcher.xml 前端控制器中加入如下配置,这样可以支持@RequiresRoles的相关权限过滤


 <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>    <!-- 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证  -->    <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>

五、自定义realm

package com.week7i.share.security;import com.week7i.share.controller.controller;import com.week7i.share.service.SystemService;import com.week7i.share.util.SpringContextHolder;import org.apache.commons.lang3.StringUtils;import org.apache.log4j.Logger;import org.apache.shiro.authc.*;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 org.springframework.stereotype.Service;/** * Created by jiangxingqi on 2017/7/19. */@Servicepublic class SystemAuthorizingRealm extends AuthorizingRealm {    private static SystemService systemService;    private static Logger logger = Logger.getLogger(controller.class);    /**     * 获取系统业务对象     */    public SystemService getSystemService() {        if (systemService == null){            systemService = SpringContextHolder.getBean(SystemService.class);        }        return systemService;    }    /**     * 授权     */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {        String currentUsername = (String)super.getAvailablePrincipal(principals);        SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();        if(StringUtils.isNotEmpty(currentUsername)){            //添加一个角色,不是配置意义上的添加,而是证明该用户拥有admin角色            String roleName=systemService.getRoleByUserName(currentUsername);            if(StringUtils.isNotEmpty(roleName)){                simpleAuthorInfo.addRole(roleName);                logger.info("已为用户["+currentUsername+"]赋予了["+roleName+"]角色");            }            //添加权限            //simpleAuthorInfo.addStringPermission("admin:manage");            return simpleAuthorInfo;        }        return simpleAuthorInfo;    }    /**     * 认证     */    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {        //获取基于用户名和密码的令牌        //实际上这个authcToken是从LoginController里面currentUser.login(token)传过来的        UsernamePasswordToken authToken = (UsernamePasswordToken)token;        logger.info("MyRealm.doGetAuthenticationInfo.token="+token);        //此处无需比对,比对的逻辑Shiro会做,我们只需返回一个和令牌相关的正确的验证信息        //第一个参数填登录用户名,第二个参数填合法的登录密码        String username=authToken.getUsername();        if(StringUtils.isEmpty(username)==false) {            String password=getSystemService().login(username);            if(StringUtils.isEmpty(password)==false){                AuthenticationInfo authInfo = new SimpleAuthenticationInfo(username, password, this.getName());                return authInfo;            }        }        //没有返回登录用户名对应的SimpleAuthenticationInfo对象时,就会在LoginController中抛出UnknownAccountException异常        return null;    }}

六、controller

package com.week7i.share.controller;/** * Created by jiangxingqi on 2017/2/9. */import com.week7i.share.service.SystemService;import org.apache.log4j.Logger;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.*;import org.apache.shiro.authz.annotation.RequiresRoles;import org.apache.shiro.subject.Subject;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;import java.util.HashMap;import java.util.Map;/** * Created by jiangxingqi on 2017/2/9. */@Controller@RequestMapping("user")public class controller {    private static Logger logger = Logger.getLogger(controller.class);    @Autowired    private SystemService service;    @RequestMapping(value = "index")    public String index(){        return "index";    }    @RequiresRoles("admin")    @RequestMapping(value = "back")    @ResponseBody    public Map fun(){        Map map=new HashMap();        String password=service.login("admin");        map.put("password",password);        return map;    }    @RequestMapping(value = {"login",""},method= RequestMethod.GET)    public String login(){        return "login";    }    @RequestMapping(value = {"login"},method= RequestMethod.POST)    public String loginSubmit(String username,String password,Model model){        UsernamePasswordToken token = new UsernamePasswordToken(username, password);        token.setRememberMe(true);        logger.debug("DefaultController.login#token="+token);        Subject currentUser = SecurityUtils.getSubject();        try {            //在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查            //每个Realm都能在必要时对提交的AuthenticationTokens作出反应            //所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法            logger.debug("user[" + username + "]do login checking");            currentUser.login(token);            logger.debug("user[" + username + "]authentication success");        }catch(UnknownAccountException uae){            logger.debug("user[" + username + "]UnknownAccountException");            model.addAttribute("error_msg", "UnknownAccountException");        }catch(IncorrectCredentialsException ice){            logger.debug("user[" + username + "]IncorrectCredentialsException");            model.addAttribute("error_msg", "IncorrectCredentialsException");        }catch(LockedAccountException lae){            logger.debug("user[" + username + "]LockedAccountException");            model.addAttribute("error_msg", "LockedAccountException");        }catch(ExcessiveAttemptsException eae){            logger.debug("user[" + username + "]ExcessiveAttemptsException");            model.addAttribute("error_msg", "ExcessiveAttemptsException");        }catch(AuthenticationException ae){            //注意:这个必须放在后面,因为这个异常可以处理所有认证失败的情况            model.addAttribute("error_msg", "authentication faild");        }        //验证是否登录成功        if(currentUser.isAuthenticated()){            logger.debug("user[" + username + "]authentication success");            return "index";        }        token.clear();        return "login";    }    @RequestMapping("logout")    public String logout(){        SecurityUtils.getSubject().logout();        return "login";    }}
六、login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>Title</title></head><body>${error_msg}<form action="/user/login" method="POST">    姓名:<input type="text" name="username"/><br/>    密码:<input type="password" name="password"/><br/>    <input type="submit" value="确认"/></form></body></html>



原创粉丝点击