zoukankan      html  css  js  c++  java
  • 在Spring中集成shiro

    1.在pom添加集成导入

     <!-- shiro的支持包 -->
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-all</artifactId>
          <version>1.4.0</version>
          <type>pom</type>
        </dependency>
        <!-- shiro与Spring的集成包 -->
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-spring</artifactId>
          <version>1.4.0</version>
        </dependency>

     2.在WEB-INF/web.xml中添加一个过滤器

     <!-- Shiro Filter is defined in the spring application context: -->
      <!--配置一个DelegatingFilterProxy这是一个下放权限,把请求让给
      <filter-name>shiroFilter</filter-name>通过shiroFilter这个名称去
      -->
      <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>

    2.写一个配置文件

    自定义一个applicationContext-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-3.0.xsd">
        <!--  DefaultSecurityManager securityManager = new DefaultSecurityManager();-->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <!--引入到securityManager的realm-->
            <property name="realm" ref="myRealm"/>
        </bean>
        <!--配置我自己的realm-->
        <bean id="myRealm" class="cn.jiedada.aisell.web.controller.shiro.MyRealm">
            <!--name无关紧要-->
            <property name="name" value="myRealm"/>
            <!---->
            <property name="credentialsMatcher">
                <!--  设置密码解析器
                 HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
                         hashedCredentialsMatcher.setHashAlgorithmName("MD5");
                        hashedCredentialsMatcher.setHashIterations(10); -->
                <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                    <property name="hashAlgorithmName" value="MD5"/>
                    <property name="hashIterations" value="10"/>
                </bean>
            </property>
        </bean>
        <!--下放请求到当前页面-->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager"/>
            <!--当我们没登陆的是否跳到当前页面-->
            <property name="loginUrl" value="/s/login.jsp"/>
            <!--登陆成功调到该页面-->
            <property name="successUrl" value="/s/index.jsp"/>
            <!--有权限的,如果没有则跳转到该页面-->
            <property name="unauthorizedUrl" value="/s/unauthorized.jsp"/>
            <!--/s/login = anon放行
             /s/permission.jsp = perms[user:index]需要user:index权限才能访问
                    /** = authc -->
    <!--        <property name="filterChainDefinitions">
                <value>
                    /s/login = anon
                    /login = anon
                    /s/permission.jsp = perms[user:index]
                    /** = authc
                </value>
            </property>-->
            <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"></property>
        </bean>
        <bean id="filterChainDefinitionMap" factory-bean="shiroFilterMapFactory" factory-method="createMap" />
        <!--配置返回shiro权限拦截的bean-->
        <bean id="shiroFilterMapFactory" class="cn.jiedada.aisell.web.controller.shiro.ShiroFilterMapFactory"/>
    
    </beans>
    View Code

    3.要把该配置写入applicationContext.xml中

    <!--把applicationContext-shiro.xml放在spring中运行-->
        <import resource="classpath:applicationContext-shiro.xml"/>

    就完成了最基础的配置

    这里是MyRealm

    package cn.jiedada.aisell.web.controller.shiro;
    
    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.apache.shiro.util.ByteSource;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class MyRealm extends AuthorizingRealm {
        /*授权
        * */
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            //设置冲数据库中传来的角色
            simpleAuthorizationInfo.setRoles(this.getRoles());
            //设置冲数据库中传来的权限
            simpleAuthorizationInfo.setStringPermissions(getPerms());
            return simpleAuthorizationInfo;
        }
        private Set getRoles(){
            Set set = new HashSet();
            set.add("admin");
            return  set;
        }
        private Set getPerms(){
            Set set = new HashSet();
            set.add("employee:index");
            return  set;
        }
        /*身份验证
        返回值null为用户名错误
        * */
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            //获得token序列
            UsernamePasswordToken token=(UsernamePasswordToken)authenticationToken;
            //获得用户名
            String username = token.getUsername();
            //去数据库查询密码
            String pwd = getUsers(username);
            if(pwd!=null){
                //验证密码,传入三个参数
                //设置盐
                ByteSource byteSource = ByteSource.Util.bytes("jiedada");
                SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,pwd,byteSource,"myshiro");
                return simpleAuthenticationInfo;
            }
            return null;
        }
        private String getUsers(String username){
            if("adimn".equals(username)){
                return "2a7e4163f7f9f316d03c3f384eeb301b";
            }
            return null;
        }
    }
    View Code

     这个比较好一点

    package cn.jiedada.crm.web.shiro;
    
    import cn.jiedada.crm.domain.Employee;
    import cn.jiedada.crm.domain.Permission;
    import cn.jiedada.crm.service.IEmployeeService;
    import cn.jiedada.crm.service.IPermissionService;
    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.apache.shiro.util.ByteSource;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class MyRealm extends AuthorizingRealm {
        @Autowired
        private IEmployeeService employeeService;
        @Autowired
        private IPermissionService permissionService;
    
        /*授权
         * */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            //设置冲数据库中传来的角色
            //simpleAuthorizationInfo.setRoles(this.getRoles());
            //设置冲数据库中传来的权限
            Set<String> pers = permissionService.findLogSn();
            simpleAuthorizationInfo.setStringPermissions(pers);
            return simpleAuthorizationInfo;
        }
        /*省份验证*/
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
           //获得token
            UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
            //获得用户名
            String username = token.getUsername();
            //在数据库中查找获得数据
            Employee employee = employeeService.findEmployeeByUsername(username);
            //判断是否为空
            if(employee==null){
                throw new UnknownAccountException(username);
            }
            //设置principal
            Object principal = employee;
            //获得数据库的密码
            Object hashedCredentials = employee.getPassword();
            ByteSource credentialsSalt = ByteSource.Util.bytes(MD5Util.SALT);
            String realmName = getName();
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal,hashedCredentials,credentialsSalt,realmName);
            return info;
        }
    
    }
    View Code

    这里是ShiroFilterMapFactory

    package cn.jiedada.aisell.web.controller.shiro;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * 用于返回下面的这些值(这里的值是有顺序的:LinkedHashMap)
     *   <value>
             /login = anon
             /s/permission.jsp = perms[user:index]
             /** = authc
        </value>
     */
    public class ShiroFilterMapFactory {
    
        public Map<String,String> createMap(){
            Map<String,String> map = new LinkedHashMap<>();
            //anon:需要放行的路径
            map.put("/login","anon");
            //perms:权限拦截
            map.put("/s/permission.jsp","perms[employee:index]");
            //authc:拦截
            map.put("/**","authc");
            return map;
        }
    }
    View Code

     因为会发送Ajax请求所以我们需要判断是否为ajax判断

    AisellPermissionsAuthorizationFilter

    package cn.jiedada.crm.web.shiro;
    
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.StringUtils;
    import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
    import org.apache.shiro.web.util.WebUtils;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * 写一个自己的Shiro来判断出我们需要的东西处理Ajax权限
     */
    public class AisellPermissionsAuthorizationFilter extends PermissionsAuthorizationFilter {
    
        @Override
        protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
            Subject subject = this.getSubject(request, response);
            //判断用户是否登陆
            if (subject.getPrincipal() == null) {
                this.saveRequestAndRedirectToLogin(request, response);
            } else {
                //只用通过HttpServletRequest才能获得请求头中的数据才能判断
                HttpServletRequest httpRequest = (HttpServletRequest) request;
                HttpServletResponse httpResponse=(HttpServletResponse)response;
                //查看是否是AjAX请求
                String xRequested = httpRequest.getHeader("X-Requested-With");
                if(xRequested!=null&&"XMLHttpRequest".equals(xRequested)){
                    //传入前需要在请求头中传入响应,让他知道我们返回的数据是AJAX请求
                    httpResponse.setContentType("text/json; charset=UTF-8");
                    //带回AJAX请求,把数据作为流传回去这里需要传出标准的json数据格式
                    httpResponse.getWriter().print( "{"success":false,"msg":"没有权限"}");
    
                }else {
                    String unauthorizedUrl = this.getUnauthorizedUrl();
                    if (StringUtils.hasText(unauthorizedUrl)) {
                        WebUtils.issueRedirect(request, response, unauthorizedUrl);
                    } else {
                        WebUtils.toHttp(response).sendError(401);
                    }
                }
            }
            return false;
        }
    }
    View Code
  • 相关阅读:
    java作用域public ,private ,protected 及不写时的区别
    JAVA的静态变量、静态方法、静态类
    栈内存 堆内存
    java
    数组 bash shell
    SYN Cookie的原理和实现
    Python 时间 time
    sysctl命令详解
    lvs
    软件工程概论个人作业01
  • 原文地址:https://www.cnblogs.com/xiaoruirui/p/11696318.html
Copyright © 2011-2022 走看看