HttpServletRequest.login不会为后续请求保持登录状态

Jan*_*ing 2 resteasy wildfly wildfly-10

HttpServletRequest.login(String, String)使用以下代码登录后,对以下请求我仍然会收到基本身份验证提示.为什么login功能在我的配置中不起作用?

我的终点:

@POST
@Path("login")
@Consumes(MediaType.APPLICATION_JSON)
public void login(@Valid LoginRequest loginRequest) {
    try {
        User user = userController.findUserByUsername(loginRequest.getUsername()).orElseThrow(NotFoundException::new);
        httpServletRequest.login(loginRequest.getUsername(), loginRequest.getPassword());
        log.info(securityContext); // not null now!
    }
    catch (ServletException e) {
        throw new NotAuthorizedException(e.getMessage(), e, AuthenticationHeaderFilter.CHALLENGE);
    }
}
Run Code Online (Sandbox Code Playgroud)

和我的 jboss-web.xml

  <?xml version="1.0" encoding="UTF-8"?>
  <jboss-web xmlns="http://www.jboss.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="
        http://www.jboss.com/xml/ns/javaee
        http://www.jboss.org/j2ee/schema/jboss-web_5_1.xsd">
    <security-domain>MyRealm</security-domain>
  </jboss-web>
Run Code Online (Sandbox Code Playgroud)

我的web.xml:

<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>MyRealm</realm-name>
</login-config>

<security-role>
    <role-name>admin</role-name>
</security-role>

<security-role>
    <role-name>user</role-name>
</security-role>

<security-constraint>
    <display-name>Authenticated content</display-name>
    <web-resource-collection>
        <web-resource-name>Authentication required</web-resource-name>
        <url-pattern>/api/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>user</role-name>
    </auth-constraint>
</security-constraint>

<security-constraint>
    <display-name>Anonymous content</display-name>
    <web-resource-collection>
        <web-resource-name>Exclude from Security</web-resource-name>
        <url-pattern>/api/me/login</url-pattern>
    </web-resource-collection>
</security-constraint>
Run Code Online (Sandbox Code Playgroud)

Arj*_*jms 5

实际上,HttpServletRequest#login的合同并不强制要求在HTTP会话期间记住经过身份验证的身份(如果已经存在),当然不应该在成功身份验证时创建HTTP会话(如果不是存在).

从技术上讲,HttpServletRequest#login调用直接进入identity store(方法的Javadoc使用术语login mechanism).身份存储是一种数据库,通常只执行凭据验证,并且不了解其环境(即不了解HTTP会话,远程EJB上下文ID或任何JCA流入安全ID).

authentication mechanism意识到它的环境,而这一次是通过调用调用HttpServletRequest#authenticate.但是,这通常会在未经过身份验证的情况下启动与用户的交互对话,如果用户恰好经过身份验证,则不记得会话中经过身份验证的身份(事实上这恰好在JBoss上工作似乎更像是巧合而不是应该发生的事情).

总而言之,Servlet规范的第13.10节确实允许容器创建HTTP会话:

容器可以创建HTTP会话对象以跟踪登录状态.如果开发人员在未对用户进行身份验证时创建会话,然后容器对用户进行身份验证,则登录后对开发人员代码可见的会话必须与登录前创建的会话对象相同,以便不会丢失会话信息.

(强调我的)

但是......如果这个文本是关于调用login()方法还是那个方法,那就不太清楚了authenticate().

简而言之,这是Java EE安全规范中的许多小缺口之一; 它没有定义如何以编程方式使用给定的用户名/密码进行登录,并明确说明您是否希望仅针对当前请求或针对HTTP会话的其余部分.

我们希望在Java EE 8的Java EE安全API(JSR 375)中修复这样的问题.