java - 如何向服务器正确验证 AngularJS 客户端

标签 java jakarta-ee authentication angularjs

我正在构建一个使用 RESTful API( Jersey )的 AngularJS 网络应用程序。

在服务器端,我使用的是 Java 应用程序服务器(详细信息是 Glassfish 4)。

我的设置如下:

  • AngularJS webapp 作为单个 war 文件部署到 Java EE 应用程序服务器。
  • RESTfulAPI(和后端逻辑)也作为 war 文件部署到同一个 Java EE 应用程序服务器。
  • AngularJS webapp 调用 REST API 来获取它需要的数据。
  • RESTful API:
    • /api/public/*对于公共(public)不受限制的访问(例如/api/public/users/signup 注册为新用户)。允许任何用户访问该区域。无需登录
    • /api/private/*用于受限访问(例如/api/private/account/{id} 以检索某些帐户特定数据)
  • 私有(private)资源受到 Java EE 内部安全概念的保护(有关 web.xml 的详细信息,请参见下文)。

Web.xml

<security-constraint>
    <web-resource-collection>
        <web-resource-name>PRIVATE REST API</web-resource-name>
        <url-pattern>/private/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
        <http-method>HEAD</http-method>
        <http-method>PUT</http-method>
        <http-method>OPTIONS</http-method>
        <http-method>TRACE</http-method>
        <http-method>DELETE</http-method>
    </web-resource-collection>
    <auth-constraint>
        <description>Have to be a USER</description>
        <role-name>USERS</role-name>
    </auth-constraint>
</security-constraint>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>userauth</realm-name>
</login-config>
<security-role>
    <description/>
    <role-name>USERS</role-name>
</security-role>

此设置适用于我,但前提是我在浏览器中手动调用 URL。 如果我未通过身份验证并访问安全区域,浏览器会要求输入用户名和密码。如果提供的凭据有效,我就可以从那里访问受限区域:没问题。

但是我怎样才能让它与 AngularJS 一起工作呢? 登录有一个 POST API 调用:/api/public/users/login您必须在其中提供表单中的凭据(用户名和密码)。

客户端代码为:

ctrls.controller('LoginController', function($scope, $http, $log, $location, UserService, RemoteServerHelperService) {
    $scope.loginDataWrong = undefined;
    $scope.login = function(credentials) {
    $http.post(RemoteServerHelperService.buildURL('/public/users/login'), credentials)
        .success(function (data, status) {
            UserService.setLoggedIn(credentials.email);
            $scope.loginDataWrong = undefined;
            $location.path('/app');
            $log.info("login attempt: successfull. User.loggedIn:" + UserService.isLoggedIn());
        }).error(function (data, status, headers, config) {
            UserService.invalidate();
            $scope.loginDataWrong = true;
            $log.info("login attempt: failed. User.loggedIn:" + UserService.isLoggedIn());
        });
    };
});

客户端代码似乎有效。我也有一些路线来保护客户端的内容,等等。那里有几篇文章详细描述了客户端代码。所以这个“片段”应该足够了。

服务器端代码是:

@POST
@Path("/login")
@Consumes(MediaType.APPLICATION_JSON)
public Response login(Credentials credentials, @Context HttpServletRequest request) {
    if (isAlreadyAuthenticated(request)) {
        try {
            request.logout();
        } catch (ServletException ex) {
            return Response.status(Status.CONFLICT).build();
        }
    }

    // not authenticated
    try {
        request.login(credentials.getEmail(), credentials.getPassword());
        return Response.ok().build();
    } catch (ServletException ex) {
        return Response.status(Status.CONFLICT).build();
    }
}

但是,这不会“验证”客户端的进一步请求。当我成功登录后在限制区域进行 API 调用时,我得到一个 403 FORBIDDEN服务器端的响应。所以我认为我做错了什么。您是否知道如何向服务器验证客户端以进行进一步请求?

一个可能的解决方案是切换到基于 FORM 的身份验证并使用 j_username 和 j_password 简单地调用 j_security_check,但现在我想坚持使用 BASIC-Authentication 并通过 RESTful API 手动执行身份验证。

设置$httpProvider.defaults.withCredentials = true;不知何故似乎没有任何效果。

更新:

感谢 lossleader 的提示,我解决了这个问题。 我删除了 login()方法,因为我希望 Java EE-Server 负责身份验证。

要访问安全区域,AngularJS webapp 必须正确设置 HTTP-Header。就我而言 $http.defaults.headers.common['Authorization'] = 'Basic <username:pw>';其中 username:password必须进行 Base64 编码。

正确设置 header 后,不会显示密码提示,AngularJS webapp 可以访问 REST API。

最佳答案

感谢 lossleader 的提示,我解决了这个问题。我删除了 login() 方法,因为我希望 Java EE-Server 负责身份验证。

要访问安全区域,AngularJS webapp 必须正确设置 HTTP-Header。在我的例子中 $http.defaults.headers.common['Authorization'] = 'Basic ';其中 username:password 必须进行 Base64 编码。

正确设置 header 后,不会显示密码提示,AngularJS webapp 可以访问 REST API。

关于java - 如何向服务器正确验证 AngularJS 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18300192/

相关文章:

ruby-on-rails - 如何在 Rails、Devise 和 Backbone.js 中使用 token 身份验证?

java - JSP 页面缓存结果的最佳实践?

java - Netbeans 登录表单

java - 对取对数空间的快速排序的混淆

java - JMM : Why this outcome is illegal?

java - 使用 servlet 时出现 Netbeans 错误

Java根据第一个数组的索引对第二个数组进行排序

java - maven 问题(Eclipse Juno)

Java - 线程 "main"java.lang.Error : Unresolved compilation problems 中的异常

javascript - 使用 PHP 根据用户名加载不同的 View