springboot整合shiro执行流程与源码解读

1.概念说明

2.使用流程说明

3.配置原理说明

4.DefaultFilter系统自带过滤器说明

1.概念说明

  subject:登录主体,一般为用户;
  realm:相当于数据源,里面实现用户认证与授权逻辑;可实现多数据源配置(一个项目中连接多种类型的数据库),本文暂不说明.
  principals:主体的属性标识,可以是用户名、邮箱、用户id等;
  credentials:证明/凭证,只有主体才知道的安全信息, 比如说密码;
  SecurityManager.java :shiro核心权限管理器,主要方法:
    登录:利用主体以及认证信息进行认证,首先从缓存中取;
    登出:从session中删除主体信息并关闭session;
    创建subject对象:创建主体对象并加入到session中;
2.使用流程说明

    1.配置信息(可参考下面代码);
    2.用户认证,可以理解成是登录,shiro框架会校验用户名密码;
    3.用户访问授权,访问带有权限注解的接口,shiro会进行授权并校验权限;授权一般是从数据库中查询用户拥有的权限,接口上权限注解用于校验用户是否拥有访问路径的权限.如果权限认证失败可进入到全局异常处理中,对异常信息进行自定义处理,返回前端.
    参考代码:
自定义realm:

package com.kawaxiaoyu.admin.admin_manage.common.shiro;

import com.kawaxiaoyu.admin.admin_manage.dao.ExclusiveShareConfigDao;
import com.kawaxiaoyu.admin.admin_manage.domain.User;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;

/**
 * @ClassName: CustomRealm
 * @Desc: 自定义realm
 * @Author: txm
 * @Date: 2021/4/20 11:27
 **/
@Component
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    private ExclusiveShareConfigDao exclusiveShareConfigDao;  // 持久层dao,用于从数据库获取用户信息

    // 授权(用户访问方法时调用)
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        // 获取用户角色集合
        // 模拟从数据库查询用户拥有的角色
        Set<String> roleSet=new HashSet<>();
        roleSet.add("admin");
        roleSet.add("guest");
        simpleAuthorizationInfo.setRoles(roleSet);

        // 获取用户权限集合
        // 模拟从数据库查询用户拥有的权限
        Set<String> permissionSet =new HashSet<>();
        permissionSet.add("/goods/findAllGoods");  // 官方推荐写法:goods:findAllGoods
        simpleAuthorizationInfo.setStringPermissions(permissionSet);

        return simpleAuthorizationInfo;
    }

    // 认证(用户登录时调用)
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        if (authenticationToken.getPrincipal() == null) {
            return null;
        }
        //获取用户名
        String name = authenticationToken.getPrincipal().toString();
        User user = exclusiveShareConfigDao.findUserIdByLogin(name);
        if (user == null) {
            //这里返回后会报出对应异常
            return null;
        } else {
            //这里验证authenticationToken和simpleAuthenticationInfo的信息
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword().toString(), getName());
            return simpleAuthenticationInfo;
        }
    }
}

shiro配置类:

package com.kawaxiaoyu.admin.admin_manage.common.shiro;

import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @ClassName: ShiroConfig
 * @Desc: 权限配置类
 * @Author: txm
 * @Date: 2021/4/20 11:36
 **/
@Configuration
public class ShiroConfig {

    /**
     * 过滤器设置:创建ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean( DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //添加Shiro内置过滤器
        /**
         * Shiro内置过滤器,可以实现权限相关的拦截器
         * 常用的过滤器(具体对应配置参考DefaultFilter.java,末尾有说明):
         * anon: 无需认证(登录)可以访问
         * authc: 必须认证才可以访问
         * user: 如果使用rememberMe的功能可以直接访问
         * perm: 该资源必须得到资源权限才可以访问
         * role: 该资源必须得到角色权限才可以访问
         */
        Map filterMap = new LinkedHashMap();

        // 将登陆的接口放出来,不然没权限访问登陆的接口
        filterMap.put("/user/login", "anon");
        // 将登陆的接口放出来,不然没权限访问退出的接口
        filterMap.put("/user/logout", "anon");
        // 保证静态资源不用认证
        filterMap.put("/static/**", "anon");
        // anon即为所有的不用认证即可访问,过滤器所有的URL都是从上到下过滤执行,将所有的/都不进行认证,是保证从方法上添加权限校验.
        filterMap.put("/**", "anon");

        // 设置认证通过之后跳转的页面,否则会默认跳转到web项目下的login.jsp
        shiroFilterFactoryBean.setLoginUrl("/index");
        //设置未授权提示页面,不用设置,全局捕获异常直接跳转到指定页面
        //shiroFilterFactoryBean.setUnauthorizedUrl("/user/noAuth");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        return shiroFilterFactoryBean;
    }

    /**
     * 核心权限控制器:创建DefaultWebSecurityManager
     */
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(CustomRealm customRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联realm
        securityManager.setRealm(customRealm);
        return securityManager;
    }

    /**
     * 开启注解支持:@RequiresRoles、@RequiresPermissions、@RequiresAuthentication、@RequiresUser、	  @RequiresGuest
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
        return authorizationAttributeSourceAdvisor;
    }
}

异常处理器(主要用于优化异常提示,不配置不影响使用):

package com.kawaxiaoyu.admin.admin_manage.excption;

import com.kawaxiaoyu.admin.admin_manage.common.util.ResultVoUtil;
import com.kawaxiaoyu.admin.admin_manage.vo.ResultVo;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

/**
 * @ClassName: GloableExcption
 * @author: txm
 * @Description: 全局异常处理类
 * @date: 2020/4/22 0022 下午 2:57
 */

//此注解表示会对controller层的异常进行处理
@ControllerAdvice
public class GloableException  {

private final Logger logger = LoggerFactory.getLogger(this.getClass());

@ExceptionHandler(Exception.class)
@ResponseBody
public ResultVo toError(Exception e, HttpServletRequest request) {
    logger.debug(e.getMessage());

    // 权限异常信息处理,还可优化
    if(e instanceof UnauthenticatedException | e instanceof UnauthorizedException){
        logger.error("业务异常:"+request.getRequestURL().toString()+":"+e.getMessage());
        return  ResultVoUtil.error("业务异常:权限不足");
    }
}

登录接口权限认证(实际项目登录接口中添加,这里仅展示重要部分):

			//添加用户认证信息
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName,password);
            //  shiro框架实现用户登陆信息验证
            subject.login(usernamePasswordToken);

注解方式进行权限控制,展示内容仅在方法上使用权限控制注解:

    @RequiresPermissions("/news/findAll")
    @RequestMapping("/findAll")
    public ResultVo findAll(Integer pageCurrent, Integer pageNum, String title) throws Exception{
    			业务处理逻辑.....
    }

3.配置原理说明

shiro配置类说明:
    配置ShiroFilterFactoryBean主要作用:主要是设置过滤指定资源,不做展开说明;
    配置DefaultWebSecurityManager作用:过滤器设置以AuthorizationAttributeSourceAdvisor设置中需要使用权限核心控制器.
    配置AuthorizationAttributeSourceAdvisor原因:
        主要是用来配置五种权限注解,在项目启动过程中加载自定义配置类时触发.具体过程如下:
AuthorizationAttributeSourceAdvisor构造方法:
在这里插入图片描述
AopAllianceAnnotationsAuthorizingMethodInterceptor构造方法中设置注解:
在这里插入图片描述
以@RequiresRoles为例说一下加载过程:
在这里插入图片描述
该构造方法中需要先创建RoleAnnotationHandler
在这里插入图片描述
创建RoleAnnotatioinHandler,执行构造方法就是将@RequiresRoles对应的class对象加载到shiro框架中顶级注解处理器AnnotationHandler.java中
在这里插入图片描述 在这里插入图片描述
自定义CustomRealm配置说明:
    自定义CustomRealm继承AuthorizingRealm,主要实现两个方法:doGetAuthorizationInfo(授权)、doGetAuthenticationInfo(认证);
    首先说doGetAuthenticationInfo,用户执行登录操作调用subject.login(usernamePasswordToken);执行就会调用该方法。
    doGetAuthorizationInfo执行逻辑:以@RequiresPermissions为例说明权限校验的主要逻辑:
AnnotationsAuthorizingMethodInterceptor.java中assertAuthorized方法,shiro框架定义了对应五种注解的方法拦截器,此方法用来判断进行访问方法中是否包含五种shiro权限注解中的一种,如果有则进入到是否满足权限的校验中.没有注解则不进行权限校验. 在这里插入图片描述
getMethodInterceptors()中五种方法拦截器关联的五种注解:@RequiresRoles(需要指定角色访问)、@RequiresPermissions(需要指定权限访问)、@RequiresAuthentication(是否经过认证或者登陆)、@RequiresUser(需要认证登录)、@RequiresGuest(未认证或者叫未登陆).
    访问接口中有@RequiresPermissions注解,DelegatingSubject.java中首先判断用户是否有principals,如果没有说明没有进行过登录认证,直接异常提示然后结束逻辑;如果有则判断用户是否拥有访问该方法的权限,主要进行校验权限的方法是AuthorizingRealm.java中isPermitted,此方法中执行的逻辑是:首先获取被访问的方法需要的权限信息(即@RequiresPermissions("/news/findAll")中的"/news/findAll"),然后调用自定义realm中doGetAuthorizationInfo执行方法获取用户拥有的权限信息,两者进行比较,如果没有则说明没有访问方法的权限,抛出异常.
    权限校验:
在这里片描述
    没有用户属性标识信息抛出的异常信息:
在这里插入图片描述
    权限校验失败异常信息: 在这里插入图片描述
    shiro项目启动信息说明:
        每次请求都会被shiro框架过滤一次,主要的逻辑是DefaultSecurityManager.java中createSubject,创建一个subject的代理对象DelegatingSubject,然后将相关信息存入缓存中,此时的subject代理对象中不包含principals(主体的属性标识,可以是用户名、邮箱、用户id,但是需要保证唯一)、credentials(认证信息,比如说密码)信息;用户登录成功之后会将自定义realm中的principals存入到subject中。
4.DefaultFilter系统自带过滤器说明

shiro配置中可以对指定路径进行指定对应的过滤器,常用的有anno、authc、logout等,这里简单说一下系统是如何根据简称指定对应的过滤器。
默认过滤器:DefaultFilter.java
在这里插入图片描述
下面简单说一下过滤器执行过程:
项目启动过程中会通过默认过滤器管理器DefaultFilterChainManager将默认管理器(DefaultFilter中过滤器)添加到集合中.用户发出请求,每个请求都会进入到路径匹配过滤器PathMatchingFilter,preHandle中的逻辑就是将shiro自定义配置请求与过滤器集合进行遍历,进入到指定过滤器中执行对应的过滤操作.
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卖柴火的小伙子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值