最近我一直在玩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;
自从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