shiro拦截认证的全过程记录

 更新时间:2021年11月30日 09:40:59   作者:IM@taoyalong  
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理,下面这篇文章主要给大家介绍了关于shiro拦截认证的相关资料,需要的朋友可以参考下

概述

Shiro是apache旗下一个开源安全框架(http://shiro.apache.org/),它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架。使用shiro就可以非常快速的完成认证、授权等功能的开发,降低系统成本。

Shiro框架三大核心对象

说明:

1)Subject :主体对象,负责提交用户认证和授权信息。

2)SecurityManager:安全管理器,负责认证,授权等业务实现。(核心)

3)Realm:领域对象,负责从数据层获取业务数据。

shrio 拦截认证全过程

 1.FilterRegistrationBean过滤注册bean

@Bean
public FilterRegistrationBean shiroFilterRegistration() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new DelegatingFilterProxy("shiroFilter"));
    //该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
    registration.addInitParameter("targetFilterLifecycle", "true");
    registration.setEnabled(true);
    registration.setOrder(Integer.MAX_VALUE - 1);
    registration.addUrlPatterns("/*");
    return registration;
}

设置过滤的bean

2.shiroFilter 实际过滤配置bean

@Bean("shiroFilter")
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
    shiroFilter.setSecurityManager(securityManager);

    //oauth过滤
    Map<String, Filter> filters = new HashMap<>(10);
    filters.put("oauth2", new Oauth2Filter());
    shiroFilter.setFilters(filters);

    Map<String, String> filterMap = new LinkedHashMap<>();
    filterMap.put("/webjars/**", "anon");
    filterMap.put("/druid/**", "anon");
    filterMap.put("/login", "anon");

    filterMap.put("/**", "oauth2");
    shiroFilter.setFilterChainDefinitionMap(filterMap);

    return shiroFilter;
}

配置oauth2Filter为过滤类 过滤对象处/webjars/** /druid/** /login 外的所有

3.过滤类Oauth2Filter 继承 AuthenTicationFilter 重写以下方法

/**
 * 验证是否有效token
 * @param request re
 * @param response res
 * @return 验证token
 * @throws Exception
 */
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
    //获取请求token,如果token不存在,直接返回401
    String token = getRequestToken((HttpServletRequest) request);
    if(StringUtils.isBlank(token)){
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setContentType("application/json;charset=utf-8");
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());

        String json = new Gson().toJson(new Result().error(ErrorCode.UNAUTHORIZED));

        httpResponse.getWriter().print(json);

        return false;
    }

    return executeLogin(request, response);
}

4.调用父类 executeLogin 进行登录验证

protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
    AuthenticationToken token = this.createToken(request, response);
    if (token == null) {
        String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken must be created in order to execute a login attempt.";
        throw new IllegalStateException(msg);
    } else {
        try {
            Subject subject = this.getSubject(request, response);
            subject.login(token);
            return this.onLoginSuccess(token, subject, request, response);
        } catch (AuthenticationException var5) {
            return this.onLoginFailure(token, var5, request, response);
        }
    }
}

5.subject.login(token); 进行登录

login方法被DelegatingSubject重写

public void login(AuthenticationToken token) throws AuthenticationException {
    **
    Subject subject = this.securityManager.login(this, token);
    **
}

6.securityManager.login(this, token) login被DefaultSecurityManager

接下来几步没那么重要省略部分

7.ModularRealmAuthenticator AuthenticationInfo 授权信息获取方法

protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
    this.assertRealmsConfigured();
    Collection<Realm> realms = this.getRealms();
    return realms.size() == 1 ? this.doSingleRealmAuthentication((Realm)realms.iterator().next(), authenticationToken) : this.doMultiRealmAuthentication(realms, authenticationToken);
}

getRealms 获取我们自己重写的Realms类,主要用户获取用户信息

8.接下来则进入我们自己写的Realms类 我的类叫Oauth2Realm

/**
 * 认证(登录时调用)
 */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    String accessToken = (String) token.getPrincipal();

    //根据accessToken,查询用户信息
    SysUserTokenEntity tokenEntity = shiroService.getByToken(accessToken);
    //token失效
    if(tokenEntity == null || tokenEntity.getExpireDate().getTime() < System.currentTimeMillis()){
        throw new IncorrectCredentialsException(MessageUtils.getMessage(ErrorCode.TOKEN_INVALID));
    }

    //查询用户信息
    SysUserEntity userEntity = shiroService.getUser(tokenEntity.getUserId());

    //转换成UserDetail对象
    UserDetail userDetail = ConvertUtils.sourceToTarget(userEntity, UserDetail.class);

    //获取用户对应的部门数据权限
    List<Long> deptIdList = shiroService.getDataScopeList(userDetail.getId());
    userDetail.setDeptIdList(deptIdList);

    //账号锁定
    if(userDetail.getStatus() == 0){
        throw new LockedAccountException(MessageUtils.getMessage(ErrorCode.ACCOUNT_LOCK));
    }

    SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userDetail, accessToken, getName());
    return info;
}

负责获取用户信息的方法

这并不是登录的过程,而是授权过滤的过程,通过token到数据库查询是否有这个用户,且没有过期,则证明已经登录。

总结

到此这篇关于shrio拦截认证的文章就介绍到这了,更多相关shrio拦截认证内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 分布式调度XXL-Job整合Springboot2.X实战操作过程(推荐)

    分布式调度XXL-Job整合Springboot2.X实战操作过程(推荐)

    这篇文章主要介绍了分布式调度XXL-Job整合Springboot2.X实战操作,包括定时任务的使用场景和常见的定时任务,通过本文学习帮助大家该选择哪个分布式任务调度平台,对此文感兴趣的朋友一起看看吧
    2022-04-04
  • Windows10安装IDEA 2020.1.2的方法步骤

    Windows10安装IDEA 2020.1.2的方法步骤

    这篇文章主要介绍了Windows10安装IDEA 2020.1.2的方法步骤,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Intellj idea新建的java源文件夹不是蓝色的图文解决办法

    Intellj idea新建的java源文件夹不是蓝色的图文解决办法

    idea打开java项目后新建的模块中,java文件夹需要变成蓝色,这篇文章主要给大家介绍了关于Intellj idea新建的java源文件夹不是蓝色的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2024-02-02
  • Java中FileWriter类的简介说明

    Java中FileWriter类的简介说明

    这篇文章主要介绍了Java中FileWriter类的简介说明,FileWriter类提供了多种写入字符的方法,包括写入单个字符、写入字符数组和写入字符串等,它还提供了一些其他的方法,如刷新缓冲区、关闭文件等,需要的朋友可以参考下
    2023-10-10
  • MyEclipse2017创建Spring项目的方法

    MyEclipse2017创建Spring项目的方法

    这篇文章主要为大家详细介绍了MyEclipse2017创建Spring项目的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • springboot大文件上传、分片上传、断点续传、秒传的实现

    springboot大文件上传、分片上传、断点续传、秒传的实现

    本文主要介绍了springboot大文件上传、分片上传、断点续传、秒传的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 将java程序打成jar包在cmd命令行下执行的方法

    将java程序打成jar包在cmd命令行下执行的方法

    这篇文章主要给大家介绍了关于将java程序打成jar包在cmd命令行下执行的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-01-01
  • Spring Cloud Consul的服务注册与发现

    Spring Cloud Consul的服务注册与发现

    这篇文章主要介绍了Spring Cloud Consul服务注册与发现的实现方法,帮助大家更好的理解和学习使用spring框架,感兴趣的朋友可以了解下
    2021-02-02
  • JVM要双亲委派的原因及如何打破它

    JVM要双亲委派的原因及如何打破它

    平时做业务开发比较少接触类加载器,但是如果想深入学习,了解类加载的原理是必不可少的.java的类加载器有哪些?什么是双亲委派?为什么要双亲委派?如何打破它?接下来本文就带大家详细介绍这些知识 ,需要的朋友可以参考下
    2021-06-06
  • 微信支付java版V3验证数据合法性(Deom)

    微信支付java版V3验证数据合法性(Deom)

    这篇文章主要介绍了微信支付java版V3验证数据合法性(Deom)的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-09-09

最新评论