Shiro(一)—— spring环境下shiro认证过程

  1. web.xml配置

    <!-- 拦截到所有请求,由spring交给shiro处理 -->
        <filter>
            <filter-name>shiroFilter</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
            <!-- 是否filter中的 init 和 destroy-->
            <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. spring-shiro.xml配置
    配置缓存管理器、凭证匹配器(散列算法,加盐,散列次数)、会话管理器、自定义Realm(可以注入凭证匹配器)、安全管理器(将自定义Realm注入)、自定义过滤器Filter、Shiro的Web过滤器(注入安全管理器,filterChainDefinitions,loginUrl等)

    	<?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:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
    	    http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--shiro核心过滤器-->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <!--
            如果配置了 loginUrl  没有认证  执行对应的login请求 
            -->
            <property name="loginUrl" value="/static/login.html"/>
    
    
            <!--配置安全管理器-->
            <property name="securityManager" ref="securityManager"></property>
    
            <!-- 配置shiro过滤器pattern -->
            <property name="filterChainDefinitions">
                <value>
                    /static/css/** = anon <!--静态文件不需要登录验证-->
                    /static/images/** = anon
                    /static/easyui/** = anon
                    /static/json/** = anon
                    /static/js/** = anon
                    /static/login.html = anon
                    /login = anon   <!--登录请求不拦截-->
                    /** = authc     <!--除指定请求外,其它所有的请求都需要身份验证-->   
                </value>
            </property>
        </bean>
    
        <!-- 配置shiro安全管理器 -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <!--注入realm-->
            <property name="realm" ref="employeeRealm"/>
        </bean>
    
        <!--自定义Realm-->
        <bean class="fei.web.shiro.realm.EmployeeRealm" id="employeeRealm">
            <!--注入凭证管理器-->
            <property name="credentialsMatcher" ref="credentialsMatcher"/>
        </bean>
    
        <!--凭证管理器-->
        <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
            <!--加密算法-->
            <property name="hashAlgorithmName" value="MD5"/>
            <!--加密次数-->
            <property name="hashIterations" value="3"/>
        </bean>
    </beans>
    
  3. LoginController中执行
    SecurityUtils.getSubject().login(token);
    token是UsernamePasswordToken类或者其子类
    token会被一直传,直到最后的自定义realm中,执行doGetAuthenticationInfo()方法,查询数据库,如果存在返回SimpleAuthenticationInfo,自动进行密码比对,判断登陆成不成功

    /**
         * @function: 认证
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    
            LOG.info("来到了认证");
            //获取身份信息
            String username = (String) token.getPrincipal();
            LOG.info("用户名:" + username);
    
            //根据用户名查询有没有当前用户
            Employee employee = employeeService.getEmployeeByUserName(username);
    
            //没有查询到或者不是管理员,直接返回null
            if (employee == null) {
                return null;
            }
    
            if (employee.getAdmin() == false){
                throw  new NotAdminException("你不是管理员,不能访问");
            }
    
            //定义加密的盐值,是ByteSource类型
            ByteSource salt = ByteSource.Util.bytes(employee.getUsername());
    
            LOG.info("密码明文:" + employee.getPassword());
    
            /**
             * @function: 数据库密码加密(因为存的还是明文)
             * 参数:加密算法,密码(需要加密的字段),加密的盐值(通常为了区分各用户,使用用户主键),加密迭代次数
             */
            SimpleHash newpassword =
                    new SimpleHash("MD5", employee.getPassword(), salt, 3);
    
            LOG.info("密码密文:" + newpassword);
    
    
            /**
             * 因为当前realm配置了凭证管理器,所以token中的密码会自动加密
             * 就是将SimpleAuthenticationInfo的密码与token的密码进行匹配判断是否可以登录成功
             * 参数: 主体,正确的密码,盐,当前realm名称
             * */
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(employee, newpassword, salt, this.getName());
    
            return info;
        }
    
  4. LoginController中捕获相关异常,返回json反馈信息给前端

    @RequestMapping("/login")
        public ResultMessage userLogin(Employee employee){
    
            ResultMessage message = new ResultMessage();
    
            try {
                TokenManager.login(employee);
                LOG.info("登录成功");
                return ResultMessage.succ();
            }catch (UnknownAccountException e){
                message.setResultCode(200);
                message.setResultMes("账户不存在");
                LOG.warn("账户不存在");
                return message;
            }catch (NotAdminException e){
            /这个是我的自定义异常
                message.setResultCode(200);
                message.setResultMes(e.getMessage());
                LOG.warn(e.getMessage());
                return message;
            }
            catch (IncorrectCredentialsException e){
                message.setResultCode(200);
                message.setResultMes("密码错误");
                LOG.warn("密码错误");
                return message;
            }catch (Exception e){
                message.setResultCode(500);
                message.setResultMes("服务器发生异常");
                LOG.error(e.getMessage());
                return message;
            }
        }
    

这就是我使用shiro进行登陆认证的流程及代码,如果有问题谢谢指正,要不点个赞吧,哈哈

猜你喜欢

转载自blog.csdn.net/shijiujiu33/article/details/89647869