首页 文章

Java EE的RESTful身份验证

提问于
浏览
19

我花了一些时间来评估可用于在 Java EE 应用程序中重新验证用户身份的选项 .

因此,请建议以下列出的选项是否有效以及有关优缺点的陈述 . 它可能是我的另一个选项,我严格地谈论java EE所以没有查询身份验证,除非可以以符合EE的方式完成,否则不会这样做

1.DIGEST / BASIC认证

<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

  • 这是一种REST友好的身份验证方式 . 您可以通过AJAX调用发送授权凭据 . 一旦用户通过身份验证,浏览器将伴随任何具有正确 Authorization: Basic/Digest QWxhZGRpbjpvcGVuIHNlc2FtZQ== 标头的请求 . 如果凭据不良,将向用户显示丑陋的浏览器登录屏幕 - 如果您可以使用它,那么BASIC / DIGEST auth就是您的选择 .

  • 在摘要的情况下,传递给服务器的字符串是MD5加密的字符串,它比Basic(这是'user:password'字符串的Base64编码)更安全,但仍然是decipherable . 因此,在安全性方面,BASIC与FORM身份验证一样安全,而DIGEST是最安全的 . 总之,如果您的网站完全是HTTPS(我的意思是 entirely ,因为如果某些资源是通过HTTP获取的,例如您的授权 Headers 将对第三方可见)您可以安全地使用BASIC / DIGEST .

  • 易于设置 .

Disadvantages

  • 退出是很棘手的 . 请参阅herehere . 确保您有一个很好的AJAX请求来验证用户,但您还需要一个?AJAX?注销用户的请求 - 触发浏览器登录窗口再次出现) . BTW好的servlet 3.0 request.logout()方法does not work properly in this case .

  • 会话超时很难实现 . 会话到期确实发生(它是servlet容器的工作),但浏览器将在下一个请求上发送授权头,从而触发重新身份验证 .

  • 没有个性化登录页面 . 没有 .

  • 难以跟踪经过身份验证的会话 .

2.基于表单的身份验证

<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>

简而言之,如果用户访问 protected/* url,则响应中的登录页面为 included . 因此,用户期望他将获得在 form-login-page 标签中配置的登录页面而不是内容 . 如果密码正常,他将被转发(302 Paged Moved Permanently)到最初请求的 protected/* url . 如果密码为NOK,则会将用户转发(永久移动分页)到错误页面 .

Advantages

  • 个性化登录页面 - 这个似乎是最受欢迎的:)

  • 注销很容易实现 . 只需要使HttpSession无效或调用request.logout()方法(Servlet 3.0) .

  • 会话超时

  • IF和ONLY如果您接受单独的登录页面,那么这是您的解决方案 .

Disadvantages

  • REST不友好(我以JAVA EE方式重新分析REST身份验证,并且始终为任何经过身份验证的主题维护服务器端状态) . 使用FORM身份验证的真正原因是,不能在浏览器之间保持一致的行为 . 这完全归功于302重定向,一些浏览器在AJAX响应函数中处理,而其他浏览器重定向整个页面(更改导航栏中的URL) . 更多细节herehere . 您无法解决302重定向问题,因此您没有为您提供FORM和REST身份验证!

3.编程身份验证

设置用于身份验证的URL . 在该URL后面,您可以拥有一个servlet,它实例化一个登录模块(JAAS方式)并调用HttpServletRequest.login(user,pass)方法以及凭据 . 如果登录失败,它应该生成401/403响应 .

您可以通过在web.xml中指定security-constraints来实现它:

<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>

在服务器端,您只需设置一个RESTFul服务,该服务对呼叫者进行身份验证 . 以下是一些示例代码:

@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

  • 个性化登录页面 .

  • AJAX / REST兼容

  • 注销URL(如果设置了URL)

  • 会话超时(容器管理)

  • 您可以在响应中返回登录数据(用户名,电子邮件,角色,组等)(非常好,因为您在成功登录后无需再次进行呼叫)

Disadvantages

  • 需要一些代码编写 .

  • 需要申请能够处理401/403响应并显示登录窗口

总之,最好的可行选择:

  • 如果您不关心会话超时或注销 - > DIGEST

  • 如果以上内容对您不起作用且您不需要嵌入式登录页面(或类似模板面板的页面),您可以使用一个页面进行身份验证 - > FORM

  • 如果上述内容对您不起作用,并且您希望全世界的所有灵活性和兼容性符合PROGRAMMATIC方法 . 您必须定义登录/注销URL,并且您的客户端代码应该能够应对401/403响应(不容易) .

真的很期待你们提出一些可行的替代解决方案 . 因为现在我讨厌采用PROGRAMMATIC方法

2 回答

  • 3

    根据我的经验,很难使用Java EE身份验证和授权服务来实现一个系统,该服务同时适用于REST服务和服务器端MVC(如JSP或JSF) . 我的所有经验都倾向于为MVC部分使用基于表单的身份验证,以及为REST服务使用某种令牌身份验证(OAuth,Kerberos,LTPA) . 对REST服务使用表单或基本身份验证通常很难实现,尽管我们这样做了,它在两个项目上运行良好 .

    它还取决于首选的服务器实现 .

  • 0

    可能有争议这些是否是RESTful,但至少可以解决以下问题:

    Keberos怎么样?使用Windows AD等身份验证服务器...

    公钥证书怎么样?依靠客户提供的证书来识别用户......

    令牌怎么样?第三方令牌发行商,如OpenID ......

相关问题