如何解决AngularJS和位于另一个域的Jersey Webservice之间的通信无法访问正确的会话
根据您使用的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/zh-CN/docs/HTTP/Access_control_CORS?redirectlocale=zh-CN&redirectslug=HTTP_access_control#section_5
解决方法
最近,我一直在使用AngularJS和Java
EE6。我已经在Jersey上构建了一个Web服务,并在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网页发布到/
login,这似乎还可以,我确实获得了正确的用户名,并且已经建立了会话。然后,如果我向/ ping发送GET请求,则确实会获得我登录时使用的用户名。
我已经在需要登录的node.js
Web服务器上部署了AngularJS应用程序。因为该服务器位于另一个域上的另一个端口上,所以我不得不经历启用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;
}
}
这确实使我能够从AngularJS向玻璃鱼上部署的Java EE 6应用程序发送不同类型的HTTP请求。
问题是,当我从AngularJS向/ login方法发送POST请求时,创建了一个会话,并且确实获得了我的用户名。但是,当我向/
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设置为true
$http.defaults.withCredentials = true;
但是,这并不能解决我的问题。我还尝试将它与config参数中的每个请求一起发送,但这也不能解决我的问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。