xmlhttprequest – AngularJS和位于不同域中的Jersey Webservice之间的通信.无法访问正确的会话

前端之家收集整理的这篇文章主要介绍了xmlhttprequest – AngularJS和位于不同域中的Jersey Webservice之间的通信.无法访问正确的会话前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
亲爱的stackoverflow读者,

最近我一直在玩AngularJS和Java EE 6.我已经和泽西建立了一个webservice,并在Glassfish上部署了这个项目.因为我需要某种身份验证和OAuth实现,或者JDBCRealm似乎过度杀戮,所以我决定在用户​​成功登录后创建一个会话.

@POST
@Path("/login")
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
public Response login(LoginDAO loginData,@Context HttpServletRequest req) {
    req.getSession().invalidate();
    loginData.setPassword(PasswordGenerator.hash(loginData.getPassword()));
    User foundUser = database.login(loginData);
    if(foundUser == null) {
        return Response.status(Status.CONFLICT).build();
    }
    req.getSession(true).setAttribute("username",foundUser.getUsername());
    return Response.ok().build();
}

@GET
@Path("/ping")
public Response ping(@Context HttpServletRequest req) {
    if(req.getSession().getAttribute("username") == null) {
        return Response.ok("no session with an username attribute has been set").build();
    }
    return Response.ok(req.getSession(true).getAttribute("username")).build();
}

这似乎工作正常,如果我发布到/从Postman或从部署在glassfish上的基本jQuery网页登录,我将获得正确的用户名,并且已经放置一个会话.如果我发送GET请求到/ ping我确实从我登录用户名.

我有一个AngularJS应用程序部署在需要登录的node.js webserver上.因为这个服务器是在另一个端口上的另一个域,我不得不忍受痛苦的启用cors.我通过构建容器响应过滤器来设置响应头.

public class CrossOriginResourceSharingFilter implements ContainerResponseFilter {
    @Override
    public ContainerResponse filter(ContainerRequest creq,ContainerResponse cresp) {
        cresp.getHttpHeaders().putSingle("Access-Control-Allow-Origin","http://localhost:8000");
        cresp.getHttpHeaders().putSingle("Access-Control-Allow-Credentials","true");
        cresp.getHttpHeaders().putSingle("Access-Control-Allow-Methods","GET,POST,DELETE,PUT");
        cresp.getHttpHeaders().putSingle("Access-Control-Allow-Headers","Content-Type,Accept,X-Requested-With");
        return cresp;
    }
}

这样做使我有可能将不同类型的HTTP请求从AngularJS发送到部署在glassfish上的Java EE 6应用程序.

问题是当我从AngularJS发送一个POST请求到/ login方法时,会创建一个会话,并且我确定我的用户名.但是当我向/ ping方法发送GET请求时,我得到“没有用户名属性的会话已被设置”通知.

我相信这与跨域防范有关,当我发送xhr请求时,我必须设置withCredentials标签.我一直在AngularJS这样做,但是还没有找到如何做到这一点.

function LoginCtrl($scope,$http) {
    $scope.login = function() {
        $http.post("glassfish:otherport/api/login",$scope.credentials).
            success(function(data) {
                console.log(data);
            }).
            error(function(data,error) {
                console.log(error);
            });
    };
};

而在另一个控制器中:

$scope.getUsername = function() {
    $http.get("glassfish:otherport/api/ping",{}).
        success(function(data) {
            $scope.username = data;
        }).
        error(function() {
            $scope.username = "error";
        })
    }

我试图设置withCredentials是真的

$http.defaults.withCredentials = true;

然而这并没有解决我的问题.我也试图发送它与config参数中的每个请求,但这也没有解决我的问题.

根据您正在使用的AngularJS版本,您可能需要在每个$http上设置它.

自从1.2你可以做:

$http.get(url,{ withCredentials: true,...})

从1.1.1可以全局配置它:

config(['$httpProvider',function($httpProvider) {
  $httpProvider.defaults.withCredentials = true;
}]).

如果您使用的是较旧版本的Angular,请尝试将配置对象传递给指定withCredentials的$http.这应该在1.1之前的版本中工作:

$http({withCredentials: true,...}).get(...)

另请参见mruelans答案:

> https://github.com/angular/angular.js/pull/1209
> http://docs.angularjs.org/api/ng.$http
> https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS?redirectlocale=en-US&redirectslug=HTTP_access_control#section_5

猜你在找的Angularjs相关文章