You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tomcat9网页证书登录按钮Java实现求助:Connector标签功能转代码

证书登录按钮实现方案(Java + Tomcat 9)

一、先确认Tomcat双向认证配置

你之前在server.xml的Connector里已经配置了证书访问,需要确保是可选双向认证(避免所有请求都强制要证书),示例配置如下:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true">
    <SSLHostConfig>
        <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                     type="RSA"
                     clientAuth="want" /> <!-- want=可选证书,true=强制所有请求要证书 -->
        <!-- 若需信任特定CA,添加truststore配置 -->
        <!-- <Certificate certificateTruststoreFile="conf/truststore.jks" /> -->
    </SSLHostConfig>
</Connector>

二、前端「Sign in with Certificate」按钮实现

按钮点击后发起HTTPS请求到后端认证接口,浏览器会自动触发证书选择弹窗(因为Tomcat配置了clientAuth="want",后端接口会明确要求证书):

<button onclick="certLogin()">Sign in with Certificate</button>
<script>
function certLogin() {
    fetch('/cert-login', {
        method: 'POST',
        credentials: 'include'
    })
    .then(res => res.json())
    .then(data => {
        data.success ? window.location.href = '/' : alert(data.message);
    })
    .catch(err => alert('请求失败:' + err));
}
</script>

三、后端Java认证接口实现(Servlet示例)

Tomcat会自动将客户端证书注入请求属性,后端只需提取并验证证书有效性即可:

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.cert.X509Certificate;

@WebServlet("/cert-login")
public class CertLoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setContentType("application/json;charset=UTF-8");
        // 从请求中获取客户端证书
        X509Certificate[] certs = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");

        if (certs == null || certs.length == 0) {
            resp.getWriter().write("{\"success\":false,\"message\":\"未选择有效证书\"}");
            return;
        }

        X509Certificate clientCert = certs[0];
        try {
            // 基础验证:检查证书是否过期
            clientCert.checkValidity();
            // 自定义验证:比如校验证书的DN(用户标识)是否在授权列表中
            String userDN = clientCert.getSubjectDN().getName();
            if (!userDN.contains("CN=授权用户")) { // 替换成你的授权规则
                resp.getWriter().write("{\"success\":false,\"message\":\"证书未授权\"}");
                return;
            }
            // 登录成功:将用户信息存入会话
            req.getSession().setAttribute("loginUser", userDN);
            resp.getWriter().write("{\"success\":true,\"message\":\"登录成功\"}");
        } catch (Exception e) {
            resp.getWriter().write("{\"success\":false,\"message\":\"证书无效:" + e.getMessage() + "\"}");
        }
    }
}

四、关键说明

  1. Tomcat已完成证书信任链验证:只要客户端证书在Tomcat的truststore中(或由truststore中的CA签发),才会被传递到后端接口
  2. 若用Spring MVC,可通过@RequestAttribute("javax.servlet.request.X509Certificate")直接获取证书数组
  3. 若要强制仅该接口要求证书,可在Tomcat的web.xml中配置安全约束,指定/cert-login需要客户端证书

内容的提问来源于stack exchange,提问作者Belle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 05:05:14