对Java EE RE​​ST风格的身份验证 [英] RESTful authentication for Java EE

查看:191
本文介绍了对Java EE RE​​ST风格的身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经花了一些时间来评估这些选项可用于REST的认证用户在 Java EE的应用程序。

所以,请建议如果下面列出的选项以及有关的优点或缺点的声明有效。这可能是我缺少的细节可能使身份验证方法是可行的。或者,它可能是有另一种选择,我已经错过了(再一次,我们正在谈论严格的Java EE这样的没有查询认证的,哪些不是,除非它可以在一个EE兼容的方式完成的)

  

1。 DIGEST / BASIC认证

 <安全约束>
     <网络资源收集和GT;
        <网上资源名称>管理< /网上资源名称>
        < URL模式> /保护/ *< / URL模式>
     < /网络资源收集和GT;
     <身份验证约束>
        <角色名称>管理< /角色名称>
     < / AUTH约束>
< /安全约束>
<登录名,配置>
    < AUTH-方法> DIGEST / BASIC< / AUTH-方法>
    <境界 - 名称>的定义,secuity-境界和LT; /领域-名称>
< /登录,配置>
 

优点

  1. 这是认证的一个REST友好的方式。您可以通过Ajax调用发送的授权证书。一旦用户通过验证后,浏览器会伴随着适当授权任何请求:基本/摘要QWxhZGRpbjpvcGVuIHNlc2FtZQ == 头。如遇恶劣凭据的用户将psented与丑陋的浏览器登录屏幕$ P $ - 如果你能忍受的话基本/摘要身份验证的方式为您。

  2. 在消化的情况下,传递到服​​务器的字符串的MD5加密的字符串,它是definetely不是基础(这是一个Base64编码'用户名:密码字符串)更安全,但仍然<一HREF =htt​​p://en.wikipedia.org/wiki/Digest_access_authentication>辨认。因此,在基本的安全而言是pretty的多安全的FORM身份验证和摘要是最安全的这一切。总之,如果你的网站是完全HTTPS(我的意思是完全,因为如果一些资源通过HTTP获取,您的授权标题,例如将是可见的第三方),你是安全的去与基本/摘要。

  3. 易于设置。

缺点

  1. 注销是棘手的落实。请参见这里和的此处 .Sure你有一个很好的AJAX请求其对用户进行认证,但你也需要有一个?AJAX?要求其注销用户 - 触发浏览器登录窗口再次出现)。顺便说一句漂​​亮的servlet 3.0 request.logout()方法不会在这种情况下
  2. 在会话超时很难实现。会话过期确实发生(这是servlet容器的工作),但浏览器将发送授权头的下一个请求,触发重认证。
  3. 在没有个性化的登录页面。无。
  4. 很难跟踪认证会话。
  

2。基于FORM的认证

 &LT;安全约束&GT;
     &LT;网络资源收集和GT;
        &LT;网上资源名称&gt;管理&LT; /网上资源名称&gt;
        &LT; URL模式&GT; /保护/ *&LT; / URL模式&GT;
     &LT; /网络资源收集和GT;
     &LT;身份验证约束&GT;
        &LT;角色名称&gt;管理&LT; /角色名称&gt;
     &LT; / AUTH约束&GT;
&LT; /安全约束&GT;
&LT;登录名,配置&GT;
    &LT; AUTH-方法&gt;表并LT; / AUTH-方法&gt;
    &LT;境界 - 名称&gt;的定义,安全领域和LT; /领域-名称&gt;
    &LT;表单登录,配置&GT;
        &LT;表单登录页&GT; /auth/login.html< /表单登录页&GT;
        &LT;形式的错误页面&GT; /auth/error.html< /表单错误页&GT;
    &LT; /表单登录,配置&GT;
&LT; /登录,配置&GT;
 

长话短说,如果用户访问一个保护/ * 网​​址,登陆页面的包含的响应。因此,而不是内容的用户希望他将获得配置的表单登录页标记的登录页面。如果密码OK,他将被转发(302分页永久移动)的最初要求保护/ * 网​​址。如果密码是挪威克朗,该用户将被转发(302分页永久移动)到错误页面。

优点

  1. 个性化登录页面 - 这一次似乎是最流行的:)
  2. 注销很容易实现。一个人需要只无效的HttpSession或致电request.logout()方法(Servlet的3.0)。
  3. 在会话超时
  4. 当且仅当您接受有一个单独的页面登录比这是你的解决方案。

缺点

  1. 在REST不友好(我不打算在休息和保持服务器端状态的哲学思想挖不RESTful的辩论。我们分析了在Java EE的方式与服务器端的状态REST认证始终保持任何经验证的主题)。什么是真的不好有关使用FORM身份验证是一个事实,就是不能跨浏览器一致的行为。而这一切都由于302重定向其中的一些浏览器的AJAX响应函数处理,而其他重定向整个页面(在导航栏上的改变URL)。更多细节here这里。你不能变通解决302重定向,以便对你没有任何形式的与REST认证的老总!
  

3。编程认证

设置进行身份验证的URL。该URL的背后,你可以有一个servlet这实例化一个登录模块(JAAS方式),并调用HttpServletRequest.login(user和pass)方法一起凭据。如果登录失败,它应该产生一个四百零三分之四百零一响应。

您可以通过只指定安全性约束在web.xml中实现它:

 &LT;安全约束&GT;
     &LT;网络资源收集和GT;
        &LT;网上资源名称&gt;管理&LT; /网上资源名称&gt;
        &LT; URL模式&GT; /保护/ *&LT; / URL模式&GT;
     &LT; /网络资源收集和GT;
     &LT;身份验证约束&GT;
        &LT;角色名称&gt;管理&LT; /角色名称&gt;
     &LT; / AUTH约束&GT;
&LT; /安全约束&GT;
 

在服务器端,您只需要设置一个RESTful服务,验证呼叫者。下面是一些示例code:

  @Path(/ AUTH)
@ApplicationPath(/休息)
公共类AuthenticationRestFacade {

@POST
@Path(/登录)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
公众用户登录信息(用户将LoginInfo,@Context HttpServletRequest的要求)抛出LoginException异常,ServletException异常{

    //讨厌的工作,周围卡塔利娜AuthenticatorBase要能
    //改变/创建会话cookie
    request.getSession();
    request.login(loginInfo.getName(),loginInfo.getPassword());
 

优点

  1. Personlized登录页面。
  2. 在AJAX / REST兼容
  3. 注销网址(URL是成立的话)
  4. 在会话超时(容器管理)
  5. 您可以在响应返回的登录信息(用户名,电子邮件,角色,组等。)(reaaaallly很好,因为你没有登录成功后做另一呼叫)

缺点

  1. 需要的code写作的一些位。
  2. 需要的应用程序能够处理四百〇三分之四百〇一反应,显示登录窗口

要得出结论,最佳可行的方案:

  1. 如果您不关心会话超时或注销 - > DIGEST
  2. 如果上述方法不为你工作,你不needto有一个嵌入式的登录页面(或模式面板样页)和你的罚款与一个页面进行认证 - > FORM
  3. 如果上述方法不为你工作,你希望所有的灵活性和在世界上的兼容性去与方案办法。你必须定义登录/注销URL,还可以将客户端code应该能够应付四百〇三分之四百〇一反应(不容易)。

真是期待为你们提出了一些可行的替代解决方案。因为现在我不想去的方案办法

解决方案

在我的经验,这是很难实现使用Java EE身份验证和授权服务的系统,将工作为REST服务和服务器端MVC像JSP或JSF与此同时。我所有的经验都倾向于使用基于表单的身份验证的MVC部分和令牌认证(OAuth的,则Kerberos,LTPA)某种对REST服务。使用形式或为REST服务基本身份验证通常是具有挑战性的实施,但我们做到了,它工作正常的两个项目。

这也取决于preferred服务器的实现。

I've been spending some time evaluating the options available for restfully authenticating a user in a Java EE application.

So, please suggest if the options listed below are valid along with the statements about advantages or disadvantages. It might be I'm missing details which might make an authentication method viable. Or it might be that there's another option which I've missed (again we're talking strictly java EE so no query authentication and what not unless it can be done in a EE compliant way )

1. DIGEST/BASIC authentication

 <security-constraint>
     <web-resource-collection>
        <web-resource-name>admin</web-resource-name>
        <url-pattern>/protected/*</url-pattern>
     </web-resource-collection>
     <auth-constraint>
        <role-name>admin</role-name>
     </auth-constraint>
</security-constraint>
<login-config>
    <auth-method>DIGEST/BASIC</auth-method>
    <realm-name>as-defined-secuity-realm</realm-name>
</login-config>

Advantages

  1. This is a REST friendly way of authenticating. You can send the authorisation credentials via an AJAX call. Once the user is authenticated, the browser will accompany any requests with the proper Authorization: Basic/Digest QWxhZGRpbjpvcGVuIHNlc2FtZQ== header. In case of bad credentials the user will be presented with the ugly browser login screen - if you can live with that then BASIC/DIGEST auth is the way for you.

  2. In the case of Digest the string passed to the server is an MD5 encrypted string, which is definetely more secure than Basic( which is a Base64 encoding of the 'user:password' string), but nevertheless decipherable. So in terms of security BASIC is pretty much as secure as FORM authentication and DIGEST is the most secure of them all. In conclusion if your site is entirely HTTPS (I mean entirely because if some resources are fetched via HTTP, your authorization headers for example will be visible to a third party) you are safe to go with BASIC/DIGEST.

  3. Easy to set up.

Disadvantages

  1. Logging out is tricky to implement. See here and here.Sure you have a nice AJAX request which authenticates the user, but you need to also have an ?AJAX? request which logs off the user - triggering the browser login window to appear again). BTW the nice servlet 3.0 request.logout() method does not work properly in this case.
  2. Session timeouts are very hard to implement. Session expiration does occur(it is the job of the servlet container), but the browser will send the authorization headers on the next request, triggering re-authentication.
  3. No personalized login page. None.
  4. Hard to keep track of authenticated sessions.

2. FORM based authentication

 <security-constraint>
     <web-resource-collection>
        <web-resource-name>admin</web-resource-name>
        <url-pattern>/protected/*</url-pattern>
     </web-resource-collection>
     <auth-constraint>
        <role-name>admin</role-name>
     </auth-constraint>
</security-constraint>
<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>as-defined-security-realm</realm-name>
    <form-login-config>
        <form-login-page>/auth/login.html</form-login-page>
        <form-error-page>/auth/error.html</form-error-page>
    </form-login-config>
</login-config>

Long story short, if user accesses a protected/* url, the login page is included in the response. So instead of the content the user expects he will get the login page configured in the form-login-page tag. If the password is OK he will be forwarded (302 Paged Moved Permanently) to the initially requested protected/* url. If password is NOK, the user will be forwarded (302 Paged Moved Permanently) to the error page.

Advantages

  1. Personalized login page - this one seems to be the most popular :)
  2. Logoff is easy to implement. One needs only invalidate the HttpSession or call the request.logout() method (Servlet 3.0).
  3. Session timeouts
  4. IF and ONLY If you accept having a separate page for login than this is the solution for you.

Disadvantages

  1. REST unfriendly (I'm not going to dig in the phylosophy of rest and the keeping server-side state is not RESTful debate. We're analyzing REST authentication in a JAVA EE way and server side state is always maintained for any authenticated subject). What is really bad about using FORM authentication is the fact that one cannot have consistent behavior across browsers. And it's all due to the 302 redirection which some browsers handle in AJAX response functions while others redirect the entire page (change URL in navigation bar). More details here and here. You cannot work around that 302 redirect so no FORM and REST authentication for you mister !!

3. Programmatic authentication

Set up a URL for authentication. Behind that URL you can have a servlet which instantiates a login module (JAAS way) and calls the HttpServletRequest.login(user,pass) method along with the credentials. It should generate a 401/403 response if login fails.

You can implement it by just specifying the security-constraints in your web.xml:

<security-constraint>
     <web-resource-collection>
        <web-resource-name>admin</web-resource-name>
        <url-pattern>/protected/*</url-pattern>
     </web-resource-collection>
     <auth-constraint>
        <role-name>admin</role-name>
     </auth-constraint>
</security-constraint>

On the server side you simply need to set up a RESTFul service which authenticates a caller. Here is some sample code:

@Path("/auth")
@ApplicationPath("/rest")
public class AuthenticationRestFacade {

@POST
@Path("/login")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public User login(User loginInfo, @Context HttpServletRequest request) throws LoginException, ServletException {

    // nasty work-around for Catalina AuthenticatorBase to be able to 
    // change/create the session cookie 
    request.getSession();
    request.login(loginInfo.getName(), loginInfo.getPassword());

Advantages

  1. Personlized login page.
  2. AJAX/REST compatible
  3. Logout URL ( if a URL is set up to do so )
  4. Session timeouts ( container managed )
  5. You can return login data (username,email,roles,groups,etc.) in the response ( reaaaallly nice because you don't have to do another call after a successful login )

Disadvantages

  1. Needs a some bit of code writing.
  2. Needs the application to be able to handle 401/403 responses and display login window

To conclude, the best viable options :

  1. If you don't care about session timeouts or logouts --> DIGEST
  2. If the above does not work for you AND you don't needto have an embedded login page (or a modal panel-like page) and you are fine with one single page for authentication --> FORM
  3. If the above does not work for you and you want all the flexibility and the compatibility in the world go with the PROGRAMMATIC approach. You have to define login/logout URL and also your client code should be able to cope with 401/403 responses (not easy).

Really looking forward for you guys to suggest some viable alternative solutions. Because right now I would HATE to go with the PROGRAMMATIC approach

解决方案

In my experience, it is hard to implement a system using Java EE authentication and authorisation service that would work for both REST services and Server side MVC like JSP or JSF at the same time. All my experience are leaning towards using Form based authentication for the MVC part and some sort of token authentication (OAuth, Kerberos, LTPA) for REST services. Using Form or Basic authentication for REST services was usually challenging to implement, although we did it and it works fine on two projects.

It also depends on the preferred server implementation.

这篇关于对Java EE RE​​ST风格的身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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