2

我目前有许多应用程序在 Wildfly 10 上运行,并使用带有 SSO 的 Picketbox 安全系统。我目前正在升级到 Wildfly 17 并已将安全配置转换为使用 Elytron 子系统,但在写入 SSO cookie 时遇到问题。我没有升级到 JEE8 安全 API。

正在迁移的应用程序之一(“app1”)非常简单,通过login-config. web.xml此应用程序正常工作:我获得了登录表单,提交了我的凭据,并且响应包括 JSESSIONIDSSO cookie。第二个应用程序(“app2”)的实现方式略有不同。它也使用login-config,但登录页面提交给自定义 servlet,该 servlet 以编程方式使用HttpServletRequest.login(username, password). 当我在此应用程序中提交我的凭据时,它们已正确验证,但没有写入 JSESSIONIDSSO cookie。

Wildfly 配置

(它最初是为 AD 设置的,但临时设置为从文件中读取用户以进行更简单的测试)

<subsystem ...>
    ...
    <application-security-domains>
        <application-security-domain name="active-directory" http-authentication-factory="ad-http-auth">
            <single-sign-on domain="localhost" key-store="sso-ad-keystore" key-alias="localhost">
                <credential-reference clear-text="ssopass"/>
            </single-sign-on>
        </application-security-domain>
    </application-security-domains>
</subsystem>
<subsystem xmlns="urn:wildfly:elytron:7.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
    <security-domains>
        ...
        <security-domain name="LocalFileDomain" default-realm="LocalFileRealm" permission-mapper="default-permission-mapper">
            <realm name="LocalFileRealm"/>
        </security-domain>
    </security-domains>
    <security-realms>
        ...
        <filesystem-realm name="LocalFileRealm">
            <file path="fs-realm-users" relative-to="jboss.server.config.dir"/>
        </filesystem-realm>
    </security-realms>
    <http>
        ...
        <http-authentication-factory name="ad-http-auth" security-domain="LocalFileDomain" http-server-mechanism-factory="global">
            <mechanism-configuration>
                <mechanism mechanism-name="FORM">
                    <mechanism-realm realm-name="active-directory"/>
                </mechanism>
                <mechanism mechanism-name="BASIC">
                    <mechanism-realm realm-name="active-directory"/>
                </mechanism>
            </mechanism-configuration>
        </http-authentication-factory>
        <provider-http-server-mechanism-factory name="global"/>
    </http>
</subsystem>

应用程序1

<login-config>
    <auth-method>BASIC?silent=true,FORM</auth-method>
    <realm-name>App Realm</realm-name>
    <form-login-config>
        <form-login-page>/login.html</form-login-page>
        <form-error-page>/noAccess.html</form-error-page>
    </form-login-config>
</login-config>
<form action="j_security_check" method="post">
    Username: <input name="j_username" type="text"/>
    Password: <input name="j_password" type="password"/>
    <input type="submit"/>
</form>

应用程序2

<login-config>
    <auth-method>BASIC?silent=true,FORM</auth-method>
    <realm-name>App Realm</realm-name>
    <form-login-config>
        <form-login-page>/login</form-login-page>
        <form-error-page>/login</form-error-page>
    </form-login-config>
</login-config>

登录表单使用 Angular 发布到登录 servlet,如下所示:

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {

    if (req.getUserPrincipal() == null) {
        String username = req.getParameter(USERNAME_FIELD);
        String password = req.getParameter(PASSWORD_FIELD);

        if (username == null || password == null) {
            setResponseStatusAndOutput(LoginResultStatus.UNAUTHORISED, resp);
            return;
        }

        try {
            Person person = this.personRepository.findByLogin(username);
            if (person != null) {
                req.login(username, password);
                req.authenticate(resp);  // I've tried with and without this line
                setResponseStatusAndOutput(LoginResultStatus.SUCCESS, resp);
            } else {
                setResponseStatusAndOutput(LoginResultStatus.UNAUTHORISED, resp);
            }
        } catch (ServletException ex) {
            setResponseStatusAndOutput(LoginResultStatus.UNAUTHORISED, resp);
        }
    } else {
        setResponseStatusAndOutput(LoginResultStatus.SUCCESS, resp);
    }
}

private void setResponseStatusAndOutput(LoginResultStatus loginResultStatus, HttpServletResponse response) throws IOException {
    response.setContentType("application/json");
    response.setStatus(loginResultStatus.getCode());
    response.getOutputStream().print(String.format("{ \"status\": \"%s\" }", loginResultStatus.getValue()));
}

Undertow 是否不会将 SSO 内容应用于以这种方式进行身份验证的请求,可能是因为我错过了过滤器链中设置它的位置?还是我做错了什么?

编辑 1: 我进行了更多测试以尝试缩小问题范围。
Wildfly 17 Elytron,发布到j_security_check:登录 OK,写入 JSESSIONIDSSO cookie。
Wildfly 17 Elytron,发布到自定义登录 servlet:登录正常,不写入 JSESSIONIDSSO cookie。
Wildfly 10 Legacy,发布到j_security_check:登录 OK,写入 JSESSIONIDSSO cookie。
Wildfly 10 Legacy,发布到自定义登录 servlet:登录 OK,写入 JSESSIONIDSSO cookie。

我创建了一个测试项目来演示这一点,其中包括 Wildfly 10 和 17 的配置文件。

4

0 回答 0