如何强制码头的会话失效后,要求使用基本身份验证凭据? [英] How to force Jetty to ask for credentials with BASIC authentication after invalidating the session?

查看:224
本文介绍了如何强制码头的会话失效后,要求使用基本身份验证凭据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用码头6.1.22使用基本身份验证我的登录机制。我第一次登录到Web应用程序,浏览器请求的用户名和密码。

I'm using jetty 6.1.22 with BASIC authentication as my login mechanism. The first time I log into the web app, the browser requests the username and password.

如果它试图注销使用session.invalidate(),会话将失效,但凭据缓存。这意味着,如果我尝试连接到一个安全的网址,我会看到一个不同的会话ID,但是对于用户名和密码,没有任何对话。

If it try to log out using a session.invalidate(), the session is invalidated but the credentials are cached. This means that if I try to connect to a secured URL, I will see a different session id but no dialog for username and password.

推荐答案

(我知道这个问题是旧的,但它的东西,其他人可能想要的答案)

基本身份验证不真正让你问什么,但你可以得到一些作品有点像你想要什么,如果你愿意忍受一些怪癖。

BASIC Authentication doesn't really allow what you're asking for, but you can get something that works a bit like what you want, if you're willing to live with some "quirks".

基本身份验证有两个方面,使人们很难以这种方式控制

BASIC Authentication has 2 aspects that make it hard to control in this way


  • 这是无状态

  • 这是客户端

这两种这些方面的功能,但他们却很难BASIC验证链接到Java的会话。这就是为什么不同的登录机制(如Java的登录表单存在)

Both of those aspects are features, but they make it hard to link BASIC authentication to Java sessions. That is why alternate login mechanisms (like Java FORM login exist)

基本身份验证是无状态结果
这意味着,客户端有完全不知道是怎么回事在服务器端,它当然没有一套基本身份验证凭据链接到一个cookie(这是主要是控制Java会话)结果的方式
会发生什么,该浏览器将与发送用户名+密码的每个的要求,直到它决定停止(一般是因为浏览器被关闭,一个新的浏览器会话创建)。结果
浏览器不知道服务器的证书做。它不知道他们是否会需要更多的,还是不行,而且不知道什么时候在服务器端已经决定了新会已经开始,它只是不断发送每个请求的用户名+密码。

BASIC Authentication is stateless
That means that the client has absolutely no idea what is going on on the server-side, and it certainly has no way of linking a set of BASIC Authentication credentials to a cookie (which is what mostly controls the java session)
What happens in that the browser will simply send the username+password with every request, until it decides to stop (generally because the browser was closed, and a new browser session was created).
The browser doesn't know what the server is doing with the credentials. It doesn't know whether they're needed any more, or not, and it doesn't know when the server side has decided that a "new session" has started, it just keeps on sending that username+password with each request.

基本身份验证是客户端结果
用户/密码对话框是由客户端来处理。所有的服务器说的是您所请求的网址需要用户名+密码,我们已经命名为安全领域'某某'。结果
服务器不知道用户是否是在一个密码每次打字,或者客户端是否已缓存他们。它不知道是否真的有一个用户那里,或者密码是否被拉出的文件。结果
服务器可以做的唯一事情是说:你需要访问该网址前给我一个用户+密码

BASIC Authentication is Client-Side
That dialog for the user/password is handled by the client. All the server says is "The URL you requested needs a username+password, and we've named this security realm 'xyz' ".
The server doesn't know whether the user is typing in a password each time, or whether the client has cached them. It doesn't know if there really is a user there, or whether the password was pulled out of a file.
The only thing the server can do is say "You need to give me a user+password before accessing this URL"

如何伪造它结果
从本质上讲,你需要检测(即使一个受过教育的猜测),当浏览器发送旧凭据,然后发出请给我一个用户+密码响应(HTTP 401)试。

How to fake it
Essentially, you need to detect (i.e. make an educated guess) when the browser is sending old credentials and then send the "Please give me a user+password" response (HTTP 401) again.

要做到这一点,最简单的方法就是在你的应用程序检测第一次用户登录该会话的过滤器,并发送 401 响应$ C $℃。是这样的:

The simplest way to do that is to have a filter in your application that detects the first time the user has logged in for that session, and sends a 401 response code. Something like:

    if(session.getAttribute("auth") == null)
    {
        response.setStatus(401);
        response.setHeader("WWW-Authenticate", "basic realm=\"Auth (" + session.getCreationTime() + ")\"" );
        session.setAttribute("auth", Boolean.TRUE);
        writer.println("Login Required");
        return;
    }

在这个例子中我已经命名的会话创建时间的领域(虽然它不是很pretty - 你可能会想以不同的方式格式化)。这意味着,在安全领域的名称每次无效会话,时间,这有助于prevent从感到困惑(为什么会问我要用户+密码再次,对于同样的境界,我只是给客户端更改一个?)。结果
新的领域名称不会混淆servlet容器,因为它永远不会看到它 - 客户端的响应不包含的领域名称

In that example I've named the realm with the creation time of the session (although it's not very pretty - you'd probably want to format it differently). That means that the name of the security realm changes each time you invalidate the session, which helps prevent the client from getting confused (why is it asking me for a user+password again, for the same realm, when I just gave one?).
The new realm name will not confuse the servlet container, because it will never see it - the client response does not include the realm name.

诀窍,虽然,它是你不希望用户得到请求他们的密码两次他们第一次登录。而且,开箱,该解决方案将做到这一点 - 一次容器要求它,然后再当你的过滤器是

The trick though, it that you don't want the user to get asked for their password twice the first time they logon. And, out of the box, this solution will do that - once for the container to ask for it, and then again when your filter does.

如何避免让2的登录框
有4个选项。

How to avoid getting 2 login boxes There are 4 options.


  1. 请这一切在code。

  2. 使用辅助会话cookie,试图告诉用户是否登录的第一次。

  3. 有你的根URL是不安全的(但它什么都不做)

  4. 让所有你的应用程序是不安全的,除1页,将用户重定向到该页面,如果他们还没有登录。

做在code

如果你很高兴做所有的安全你自己的servlet /过滤器里面,并没有得到来自servlet容器(码头)的帮助下那么这是不是太难。您只需关闭基本认证在你的web.xml,做这一切在code。 (有工作的公平一点,你需要确保你没有留下任何安全漏洞打开,但它的概念很容易的)结果
大多数人并不想这样做。

If you're happy to do all of the security inside your own servlet/filter, and get no help from the servlet container (Jetty) then that's not too hard. You simply turn off BASIC auth in your web.xml, and do it all in code. (There's a fair bit of work, and you need to make sure you don't leave any security holes open, but it's conceptually quite easy)
Most people don't want to do that.

中的Cookie 结果
在用户登录到应用程序后,您可以设置在浏览器会话结束时到期的cookie(认证)。此cookie是联系在一起的浏览器会话和不可以到Java会话。结果
当你的无效Java会话 - 的的无效的身份验证的cookie的结果。
如果用户登录到一个的新鲜的Java会话(即 session.getAttribute(AUTH)== NULL ),但仍然有这个身份验证的,那么你知道他们现有的浏览器会话中重新使用,而且的可能的重复使用现有的HTTP认证证书。
在这种情况下,你做的 401 诱骗,强迫他们提供新的凭据。

Secondary Cookies
After a user logins in to your application, you can set a cookie ("authenticated") that expires at the end of the browser session. This cookie is tied to the browser session and not to the Java session.
When you invalidate the Java session - do not invalidate the "authenticated" cookie.
If a user logs in to a fresh java session (i.e. session.getAttribute("auth")==null), but still has this "authenticated" then you know that they're re-using an existing browser session and are probably re-using existing HTTP authentication credentials. In that case you do the 401 trick to force them to give new credentials.

无抵押根网址结果
如果你的根URL是不安全的,你知道,这是你的用户总是登录该网址,那么你可以简单地把你的权威性在那个URL / 401 检查,它会解决这个问题。
但要确保你不小心打开一个安全漏洞。结果
此网址不应该有比将用户重定向到真正的应用程序(即固定)

Unsecured root URL
If your root URL is unsecured, and you know that this is the URL that your users always login to, then you can simply put your "auth"/401 check at that URL, and it will solve the problem. But make sure you don't accidentally open a security hole.
This URL should not have any functionality other than redirecting users to the "real" app (that is secured)

单安全网址结果
有固定1 URL(例如/登录)。结果
还有你的权威性/ 401 过滤器,对所有页面(除登录之外的)其他过滤器(或在同一个过滤器额外的code),检查是否 request.getUserPrincipal()设置。如果不是,将用户重定向到/登录。

Single secured URL
Have 1 URL that is secured (e.g. "/login").
As well as your "auth"/401 filter, have another filter (or additional code in the same filter) on all pages (other than login) that checks whether request.getUserPrincipal() is set. If not, redirect the user to "/login".

的简单的解决方案结果
只是使用的一种形式登录方法,而不是基本身份验证。它的设计来解决这个问题。

The much easier solution
Just use a FORM login method instead of BASIC authentication. It's designed to solve this problem.

这篇关于如何强制码头的会话失效后,要求使用基本身份验证凭据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆