小工具知识网

当前位置: 首页 > 行业知识 > springboot项目如何使用tomcat来完成Basic Auth认证

行业知识

springboot项目如何使用tomcat来完成Basic Auth认证

2026-11-08 21:44:09 来源:互联网转载

问题场景:

���口需要经过Basic Auth认证之后才能继续访问

假如项目需要把一些接口加上安全认证访问限制,比如这里使用比较简单的Basic Auth认证,那么应该如何使用tomcat的自带的认证机制来完成访问限制呢。


解决方案

如果不借助tomcat的认证机制来完成接口访问限制,最先想到的就是自己写一个Filter类,拦截需要认证的接口,如果用户请求头中传入的Authorization字段解析后用户名和密码不对就给用户响应一个401状态码,这种自定义Filter参考之前的文章。

针对SpringBoot Actuator未授权访问端点问题

下面演示如何用tomcat提供的类完成认证,先看下代码整体思路

package com.promote.demo.config;import lombok.SneakyThrows;import org.apache.catalina.Context;import org.apache.catalina.authenticator.BasicAuthenticator;import org.apache.catalina.connector.Request;import org.apache.catalina.realm.GenericPrincipal;import org.apache.catalina.realm.RealmBase;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;import org.springframework.context.annotation.Configuration;import java.security.Principal;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;@Configurationpublic class WebSecurityConfig implements TomcatContextCustomizer {    @Value("${basic.auth.username}")    private String username;    @Value("${basic.auth.password}")    private String password;    @SneakyThrows    @Override    public void customize(Context context) {        CustomAuthenticator authenticator = new CustomAuthenticator();        authenticator.setCharset("UTF-8");        //定义数据源realm这里提供两种方式        //1.方式一:使用一个内存数据源来存放用户名和密码,也有很多其他的realm可以自行研究        //MemoryRealm realm = new MemoryRealm();        //把用户名和密码放在类路径下        //realm.setPathname("classpath:users.xml");        //把用户名和密码放在某个文件路径下        //realm.setPathname("D:\data\users.xml");        //2.方式二:自定义一个realm,可以更灵活,比如这里的用户名和密码可以自己配置在配置文件中        CustomRealm realm = new CustomRealm();        realm.addUser(username, password);        context.setRealm(realm);        //当请求过来的时候会先进入tomcat的pipeline中,每个pipeline有多个value组件来处理请求,类似于Filter链;        //这里我们定义的CustomAuthenticator也是属于value组件,当请求在管道中的所有组中走一遍之后才会到达Filter        context.getPipeline().addValve(authenticator);    }    /**     * BasicAuthenticator里面已经做了相关的身份验证逻辑     */    public static class CustomAuthenticator extends BasicAuthenticator {        /**         * 判断哪些路径需要权限校验,可以根据实际项目进行判定         *         * @param request The request currently being processed         * @return 是否需要权限校验         */        @Override        protected boolean isContinuationRequired(Request request) {            String path = request.getRequestURI();            //这里假设/api路径开头的url都需要进行权限校验            return path.startsWith("/api");        }    }    /**     * 可以自定义Realm需要继承抽象类RealmBase,并实现getPassword和getPrincipal方法     */    public static class CustomRealm extends RealmBase {        private final Map principals = new HashMap();        /**         * 添加用户         *         * @param username 用户名         * @param password 密码         */        public void addUser(String username, String password) {            principals.put(username, new GenericPrincipal(username, password, new ArrayList()));        }        @Override        protected String getPassword(String username) {            GenericPrincipal principal = principals.get(username);            if (principal != null) {                return principal.getPassword();            } else {                return null;            }        }        @Override        protected Principal getPrincipal(String username) {            return principals.get(username);        }    }}

步骤一:

首先我们需要写一个配置类实现TomcatContextCustomizer的接口,这个接口是springboot启动阶段提供给用户操作tomcat容器的接口,可以灵活配置一些业务。

步骤二:

我们需要借助tomcat中的BasicAuthenticator类来完成Basic Auth认证,这里面有比较成熟的Basic Auth认证逻辑,直接拿来使用。需要写一个类继承BasicAuthenticator并重写isContinuationRequired方法,在这个方法里面灵活判断哪些接口需要权限认证,这里我们定义/api开头接口都需要认证,然后把这个BasicAuthenticator类加到tomcat容器的pipeline中。tomcat还提供了其他的认证方式,如表单认证,这个是基于session的,感兴趣的可以自行测试。

步骤三:

我们需要定一个数据源来存放用户名和密码,这个数据源在tomcat中叫Realm,和Shrio中的Realm有些类似,tomcat默认提供了一些Realm,有内存Realm,数据库Realm等,看下Realm的关系图。

如果使用MemoryRealm,需要配置一个xml文件,文件内容如下,其实就是和tomcat安装包confg目录下的tomcat-users.xml文件内容是一样的,需要指定这个文件的位置,可以放在类路径下,也可以放在磁盘路径下。

  

由于是使用spring的配置文件来管理用户名和密码,不想使用MemoryRealm,这里自定义了一个CustomRealm来存放用户名和密码,比较灵活。

其他详细解释参考代码注释

运行效果图

未认证界面效果

取消认证效果

结语

由于认证机制是在tomcat的pipeline中完成的,还没有走到Filter,只有认证通过请求才会继续走到Filter然后再走到springmvc的interceptor,所以一定程度上性能会更好一点

tomcat的pipeline是什么参考这篇文章

上一篇:服务器倒闭怎么处理好?

下一篇:怎么开服务器联机服务器?