AngularJS$http、CORS和Jersey的基本身份验证

AngularJS$http、CORS和Jersey的基本身份验证,angularjs,cors,jersey,basic-authentication,Angularjs,Cors,Jersey,Basic Authentication,我正在学习AngularJS。我已经用带有基本身份验证的CORS创建了示例项目。我的服务器端代码是Jersey Rest。但我还是得到了403个禁止的错误。我不明白。我错过了什么吗。我的代码如下。请帮我解决它 服务器代码-- /* * This is the controller level Code to get all UserlogInHistoryAngular * information */ @GET @Path("/getall") @Produces({ MediaT

我正在学习AngularJS。我已经用带有基本身份验证的
CORS
创建了示例项目。我的服务器端代码是Jersey Rest。但我还是得到了403个禁止的错误。我不明白。我错过了什么吗。我的代码如下。请帮我解决它


服务器代码--

/*
 * This is the controller level Code to get all UserlogInHistoryAngular
 * information
 */
@GET
@Path("/getall")
@Produces({
  MediaType.APPLICATION_XML,
  MediaType.APPLICATION_JSON
})
public Response getAllUserLogInHistoryAngular() {
  log.info("Controller layer for Get All UserlogInHistory");
  UserLoginHistoryService userLogInHistoryService = new UserLoginHistoryService();

  GenericEntity < List < UserLogInHistory >> userLoginHistory = new GenericEntity < List < UserLogInHistory >> (
    userLogInHistoryService.getAllUserlogInHisotry()) {};

  return Response
    .status(200)
    .entity(userLoginHistory)
    .header("Access-Control-Allow-Credentials", true)
    .header("Access-Control-Allow-Origin", "*")
    .header("Access-Control-Allow-Methods",
      "GET, POST, DELETE, PUT, OPTIONS")
    .header("Access-Control-Allow-Headers",
      "Origin, X-Requested-With, Content-Type, Accept, Authorization, X-CSRF-Token, Accept-Version, Content-Length, Content-MD5,  Date, X-Api-Version, X-File-Name")
    .allow("OPTIONS").build();    
}    
}
var myapp = angular
  .module('myapp', ['angularUtils.directives.dirPagination']);

myapp.config(function($httpProvider) {
  //Enable cross domain calls
  $httpProvider.defaults.withCredentials = true;
  $httpProvider.defaults.useXDomain = true;
});


myapp.controller('customerController', function($scope, $http) {
      var encodingstring = window.btoa("numery" + ":" + "password");

      console.log(encodingstring);

      $http({
        withCredentials: true,
        headers: {
          'Authorization': 'Basic ' + encodingstring,
          'Content-Type': 'application/json; charset=utf-8'
        },
        method: "GET",
        url: "http://localhost:8080/userloginhistoryapi/rest/secured/userloginhistory/getall"
      }).then(function(response) {
        $scope.lstUser = response.data;
        //$log.info(response);

        console.log(response.data);
        console.log($scope.lstUser);
      })

      $scope.sortColumn = "name";
      $scope.reverseSort = false;

      $scope.sortData = function(column) {
        $scope.reverseSort = ($scope.sortColumn == column) ? !$scope.reverseSort : false;
        $scope.sortColumn = column;
      };

      $scope.getSortColumn = function(column) {

        if ($scope.sortColumn == column) {
          return $scope.reverseSort ? 'arrow-down' : 'arrow-up';
        }
        return '';
      };

      function getSelectedIndex(id) {
        for (var i = 0; i < $scope.listCustomers.length; i++)
          if ($scope.listCustomers[i].id == id)
            return i
        return -1;
      }; 
angular.js:13018 OPTIONS http://localhost:8080/userloginhistoryapi/rest/secured/userloginhistory/getall 403 (Forbidden)
(anonymous) @ angular.js:13018
sendReq @ angular.js:12744
serverRequest @ angular.js:12485
processQueue @ angular.js:17396
(anonymous) @ angular.js:17444
$digest @ angular.js:18557
$apply @ angular.js:18945
bootstrapApply @ angular.js:1939
invoke @ angular.js:5108
doBootstrap @ angular.js:1937
bootstrap @ angular.js:1957
angularInit @ angular.js:1842
(anonymous) @ angular.js:35431
trigger @ angular.js:3491
(index):1 Failed to load http://localhost:8080/userloginhistoryapi/rest/secured/userloginhistory/getall: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8081' is therefore not allowed access. The response had HTTP status code 403.
angular.js:15018 Possibly unhandled rejection: {"data":null,"status":-1,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","withCredentials":true,"headers":{"Authorization":"Basic bnVtZXJ5OnBhc3N3b3Jk","Accept":"application/json, text/plain, */*"},"url":"http://localhost:8080/userloginhistoryapi/rest/secured/userloginhistory/getall"},"statusText":"","xhrStatus":"error"}
(anonymous) @ angular.js:15018
(anonymous) @ angular.js:11302
processChecks @ angular.js:17428
$digest @ angular.js:18557
$apply @ angular.js:18945
done @ angular.js:12799
completeRequest @ angular.js:13056
requestError @ angular.js:12972
error (async)
(anonymous) @ angular.js:12985
sendReq @ angular.js:12744
serverRequest @ angular.js:12485
processQueue @ angular.js:17396
(anonymous) @ angular.js:17444
$digest @ angular.js:18557
$apply @ angular.js:18945
bootstrapApply @ angular.js:1939
invoke @ angular.js:5108
doBootstrap @ angular.js:1937
bootstrap @ angular.js:1957
angularInit @ angular.js:1842
(anonymous) @ angular.js:35431
trigger @ angular.js:3491
VM2032:185 [CodeLive] HTTP detected: Connecting using WS
VM2032:109 [CodeLive] Connected to CodeLive at ws://127.0.0.1:42529
bundle.js:10 license url https://www.genuitec.com/go/webclipse-buy-now

这就是发生的事情。这是一个
选项
请求。此请求发生在实际请求之前。它与服务器进行检查,以查看请求是否被允许。作为对飞行前请求的响应,服务器应该发回
Access-Control-X-X
头,就像您在
getAllUserLogInHistoryAngular
方法中一样

因此,在飞行前的情况下,它会点击基本的身份验证过滤器并自动被拒绝,而不添加CORS响应头。将CORS响应头放在resource方法中没有任何作用,也没有任何用处。通常,COR应该在一个过滤器中处理,以便它在命中资源方法之前处理所有请求

这是你应该做的。与基本身份验证一样,使用
ContainerRequestFilter
处理CORS。您希望在身份验证筛选器之前调用此筛选器,因为CORS预飞行不关心身份验证,并且它不会随请求发送身份验证凭据。在这个过滤器中,您应该检查它是否是CORS飞行前请求。通常,这可以通过检查
选项
方法以及是否存在
原点
标题来完成。如果是飞行前,则中止请求并在
ContainerResponseFilter
中添加CORS标头。可能看起来像

@Provider
@PreMatching
public class CorsFilter implements ContainerRequestFilter, ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext request) throws IOException {
        if (isPreflightRequest(request)) {
            request.abortWith(Response.ok().build());
            return;
        }
    }

    private static boolean isPreflightRequest(ContainerRequestContext request) {
        return request.getHeaderString("Origin") != null
                && request.getMethod().equalsIgnoreCase("OPTIONS");
    }

    @Override
    public void filter(ContainerRequestContext request, ContainerResponseContext response)
            throws IOException {
        if (request.getHeaderString("Origin") == null) {
            return;
        }
        if (isPreflightRequest(request)) {
            response.getHeaders().add("Access-Control-Allow-Credentials", "true");
            response.getHeaders().add("Access-Control-Allow-Methods",
                "GET, POST, PUT, DELETE, OPTIONS, HEAD");
            response.getHeaders().add("Access-Control-Allow-Headers",
                "Origin, X-Requested-With, Content-Type, Accept, Authorization, X-CSRF-Token, " +
                "Accept-Version, Content-Length, Content-MD5,  Date, X-Api-Version, X-File-Name");
        }
        response.getHeaders().add("Access-Control-Allow-Origin", "*");
    }
}
请注意,它是一个
@PreMatching
过滤器,这将导致在您的身份验证过滤器之前调用它(假设过滤器不是一个预匹配过滤器,在这种情况下,您还应该使用
@Priority
注释)

此筛选器所做的是检查请求是否为飞行前请求,如果是,则以200中止整个请求,这会导致请求跳过资源方法,跳过它之后的所有其他请求筛选器,并跳转到响应筛选器。在响应过滤器中,我们通过检查前面设置的属性来检查它是否为飞行前。如果是,则设置CORS响应头。如果您想了解有关CORS的更多信息以及有关此特定筛选器实现的更多信息,请访问

所以不,这是将要发生的事情的流程

客户端浏览器服务器
------                    -------                    ------
请求端点------->记住请求------->发回CORS
但首先发送响应头
来自CorsFilter的CORS预飞
|      
抓住原始Skips CorsFilter,
转到身份验证筛选器,
转到资源
发送资源响应
|

Handle response您是否检查过任何REST客户端(如Postman)中的服务是否与凭据一起工作正常?您的基本身份验证发生在哪里?服务在Postman和SoapUI中工作正常。我两个都查过了。我使用ContainerRequestFilter进行基本身份验证