Spring Boot+Shiro实现一个Http请求的Basic认证

 更新时间:2021年06月15日 12:02:23   作者:H.U.C-王子  
本文向向大家仔细的介绍了如何使用Shiro实现一个Http请求的Basic认证,有此需求的朋友可以参考下本文

前言

今天跟小伙伴们分享一个实战内容,使用Spring Boot+Shiro实现一个简单的Http认证。

场景是这样的,我们平时的工作中可能会对外提供一些接口,如果这些接口不做一些安全认证,什么人都可以访问,安全性就太低了,所以我们的目的就是增加一个接口的认证机制,防止别人通过接口攻击服务器。

至于Shiro是什么,Http的Basic认证是什么,王子就简单介绍一下,详细内容请自行了解。

Shiro是一个Java的安全框架,可以简单实现登录、鉴权等等的功能。

Basic认证是一种较为简单的HTTP认证方式,客户端通过明文(Base64编码格式)传输用户名和密码到服务端进行认证,通常需要配合HTTPS来保证信息传输的安全。

实践部分

首先说明一下测试环境。

王子已经有了一套集成好Shiro的Spring Boot框架,这套框架详细代码就不做展示了,我们只来看一下测试用例。

要测试的接口代码如下:

/**
 * @author liumeng
 */
@RestController
@RequestMapping("/test")
@CrossOrigin
public class TestAppController extends BaseController {
    /**
     * 数据汇总
     */
    @GetMapping("/list")
    public AjaxResult test()
    {
        return success("测试接口!");
    }
}

使用Shiro,一定会有Shiro的拦截器配置,这部分代码如下:

/**
     * Shiro过滤器配置
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
    {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // Shiro的核心安全接口,这个属性是必须的
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 身份认证失败,则跳转到登录页面的配置
        shiroFilterFactoryBean.setLoginUrl(loginUrl);
        // 权限认证失败,则跳转到指定页面
        shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
        // Shiro连接约束配置,即过滤链的定义
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 对静态资源设置匿名访问
        filterChainDefinitionMap.put("/favicon.ico**", "anon");
        filterChainDefinitionMap.put("/lr.png**", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/docs/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/ajax/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/lr/**", "anon");
        filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
        // 退出 logout地址,shiro去清除session
        filterChainDefinitionMap.put("/logout", "logout");
        // 不需要拦截的访问
        filterChainDefinitionMap.put("/login", "anon,captchaValidate");
        filterChainDefinitionMap.put("/ssoLogin", "anon");     // 开启Http的Basic认证
        filterChainDefinitionMap.put("/test/**", "authcBasic"); 
        // 注册相关
        filterChainDefinitionMap.put("/register", "anon,captchaValidate");

        Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
        filters.put("onlineSession", onlineSessionFilter());
        filters.put("syncOnlineSession", syncOnlineSessionFilter());
        filters.put("captchaValidate", captchaValidateFilter());
        filters.put("kickout", kickoutSessionFilter());
        // 注销成功,则跳转到指定页面
        filters.put("logout", logoutFilter());
        shiroFilterFactoryBean.setFilters(filters);

        // 所有请求需要认证authcBasic
        filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }

这里我们要关注的是代码中的

filterChainDefinitionMap.put("/test/**", "authcBasic");
这部分代码,它指定了我们的测试接口启动了Http的Basic认证,这就是我们的第一步。

做到这里我们可以尝试的去用浏览器访问一下接口,会发现如下情况:

这就代表Basic认证已经成功开启了,这个时候我们输入系统的用户名和密码,你以为它就能成功访问了吗?

答案是否定的,我们只是开启了认证,但并没有实现认证的逻辑。

王子通过阅读部分Shiro源码,发现每次发送请求后,都会调用ModularRealmAuthenticator这个类的doAuthenticate方法,源码如下:

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

可以看出,这个方法主要就是对Realm进行了管理,因为我们的系统本身已经有两个Ream了,针对的是不同情况的权限验证,所以为了使用起来不冲突,我们可以继承这个类来实现我们自己的逻辑,在配置类中增加如下内容即可:

@Bean
    public ModularRealmAuthenticator modularRealmAuthenticator(){
        //用自己重新的覆盖
        UserModularRealmAuthericator modularRealmAuthericator = new UserModularRealmAuthericator();
        modularRealmAuthericator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
        return modularRealmAuthericator;
    }

然后在我们自己的UserModularRealmAuthericator类中重写doAuthenticate方法就可以了,这里面的具体实现逻辑就要看你们自己的使用场景了。

我们可以自己新创建一个Realm来单独校验Basic认证的情况,或者共用之前的Realm,这部分就自由发挥了。

大概内容如下:

public class UserModularRealmAuthericator extends ModularRealmAuthenticator {
    private static final Logger logger = LoggerFactory.getLogger(UserModularRealmAuthericator.class);

    @Override
    protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
        assertRealmsConfigured();
        //强制转换返回的token
        UsernamePasswordToken  usernamePasswordToken = (UsernamePasswordToken) authenticationToken;//所有Realm
        Collection<Realm> realms = getRealms();
        //最终选择的Realm
        Collection<Realm> typeRealms = new ArrayList<>();
        for(Realm realm:realms){
            if(...){ //这部分是自己的逻辑判断,过滤出想要使用的Realm
                typeRealms.add(realm);
            }
        }
        //判断是单Realm 还是多Realm
        if(typeRealms.size()==1){
            return doSingleRealmAuthentication(typeRealms.iterator().next(),usernamePasswordToken);
        }else{
            return doMultiRealmAuthentication(typeRealms,usernamePasswordToken);
        }
    }
}

Realm的具体实现代码这里就不做演示了,无非就是判断用户名密码是否能通过校验的逻辑。如果不清楚,可以自行了解Realm的实现方式。

Realm校验实现后,Basic认证就已经实现了。

测试部分

接下来我们再次使用浏览器对接口进行测试,输入用户名和密码,就会发现接口成功响应了。

我们来抓取一下请求情况

可以发现,Request Header中有了Basic认证的信息Authorization: Basic dGVzdDoxMjM0NTY=

这部分内容是这样的,Basic为一个固定的写法,dGVzdDoxMjM0NTY=这部分内容是userName:Password组合后的Base64编码,所以我们只要给第三方提供这个编码,他们就可以通过编码访问我们的接口了。

使用PostMan测试一下

可以发现接口是可以成功访问的。

总结

到这里本篇文章就结束了,王子向大家仔细的介绍了如何使用Shiro实现一个Http请求的Basic认证,是不是很简单呢。

以上就是Spring Boot+Shiro实现一个Http请求的Basic认证的详细内容,更多关于Spring Boot+Shiro Http请求的Basic认证的资料请关注脚本之家其它相关文章!

相关文章

  • Win10 IDEA如何连接虚拟机中的Hadoop(HDFS)

    Win10 IDEA如何连接虚拟机中的Hadoop(HDFS)

    在虚拟机上配置Hadoop并修改core-site.xml文件,设置IP为局域网地址,IDEA中创建Maven项目,添加依赖,并检查Hadoop重启和端口转发,提供test.bat文件,通过修改IP简化使用过程
    2024-11-11
  • 通俗易懂的Java常见限流算法具体实现

    通俗易懂的Java常见限流算法具体实现

    这篇文章主要介绍了Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的优点和缺点,需要的朋友可以参考下
    2025-02-02
  • Java中JDBC的使用教程详解

    Java中JDBC的使用教程详解

    Java语言操作数据库 JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。本文讲解了JDBC的使用方法,需要的可以参考一下
    2022-06-06
  • 学习Java中的List集合

    学习Java中的List集合

    这篇文章主要介绍了学习Java中的List集合,List是一个有序集合, 说是集合,其实只是只是Collection接口的一个子接口,下面关于List的相关资料 需要的小伙伴可以参考一下,希望对你有所帮助
    2022-02-02
  • Java并发编程中的Exchanger解析

    Java并发编程中的Exchanger解析

    这篇文章主要介绍了Java并发编程中的Exchanger解析,Exchanger用于线程间数据的交换,它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据,这两个线程通过exchange方法交换数据,如果第一个线程先执行exchange()方法,需要的朋友可以参考下
    2023-11-11
  • Spring Cloud Hystrix 服务降级限流策略详解

    Spring Cloud Hystrix 服务降级限流策略详解

    这篇文章主要为大家介绍了Spring Cloud Hystrix 服务降级限流策略详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • logback 实现给变量指定默认值

    logback 实现给变量指定默认值

    这篇文章主要介绍了logback 实现给变量指定默认值操作,具有很好的参考家价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 使用 Spring Boot 2.0 + WebFlux 实现 RESTful API功能

    使用 Spring Boot 2.0 + WebFlux 实现 RESTful API功能

    什么是 Spring WebFlux, 它是一种异步的, 非阻塞的, 支持背压(Back pressure)机制的Web 开发框架.下面通过本文给大家介绍使用 Spring Boot 2.0 + WebFlux 实现 RESTful API功能,需要的朋友参考下吧
    2018-01-01
  • jdbc连接oracle数据库功能示例

    jdbc连接oracle数据库功能示例

    这篇文章主要介绍了jdbc连接oracle数据库功能,结合实例形式详细分析了java基于jdbc连接Oracle数据库的具体操作步骤与相关实现技巧,需要的朋友可以参考下
    2017-01-01
  • 如何基于Jenkins构建Docker镜像

    如何基于Jenkins构建Docker镜像

    这篇文章主要介绍了基于Jenkins构建Docker镜像,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11

最新评论