getUserPrincipal返回null

时间:2015-02-02 15:03:49

标签: java angularjs

我使用AngularJS作为前端,使用Java EE作为后端。 我使用RESTful服务创建了两种登录和注销方法:

@POST
@Path("login")
@Produces("application/json")
public Response login(@Context HttpServletRequest req, UserTable user) {
    if (req.getUserPrincipal() == null) {
        try {
            req.login(user.getUsername(), user.getPassword());
        } catch (ServletException e) {
            return Response.status(Response.Status.BAD_REQUEST).type("text/plain").entity("Login or Password is incorrect").build();
        }
    } else {
        return Response.status(Response.Status.OK).type("text/plain").entity("You are already logged in").build();
    }
    return Response.status(Response.Status.OK).type("text/plain").entity("Login successfull").build();
}

@GET
@Path("logout")
@Produces("application/json")
public Response logout(@Context HttpServletRequest req) {
    try {
        req.logout();
        req.getSession().invalidate();
    } catch (ServletException e) {
        return Response.status(Response.Status.BAD_REQUEST).type("text/plain").entity("Can not logout").build();
    }
    return Response.status(Response.Status.OK).type("text/plain").entity("Logout successfull").build();
}

在前端,我使用以下方法:

    $http.post(apiUrl + 'usertable/login', {
        username: 'admin',
        password: 'admin'
    });

    $http.get(apiUrl + 'usertable/logout').success(function (a) {
        var o = a;
    });

我可以成功登录:

FINEST:   JDBC login succeeded for: admin groups:[Admin]
FINE:   JAAS login complete.
FINE:   JAAS authentication committed.
FINE:   Password login succeeded for : admin

但是当我尝试注销或再次登录时,getUserPrincipal()返回null。我做错了什么?

2 个答案:

答案 0 :(得分:2)

在之前手动创建HTTP会话,然后调用login方法。

您可以通过调用HttpServletRequest.getSession()方法执行此操作,如下所示:

req.getSession(true); // Creates a new HTTP Session BEFORE the login.
req.login(user.getUsername(), user.getPassword());

确保服务器在响应中返回JSESSIONID cookie。之后,浏览器将处理它并将其发送到服务器,而无需您担心或自行处理。

登录回复

enter image description here

请求进一步通话(服务电话,检查登录,退出等)

enter image description here

更新

也许你需要告诉AngularJS发送Cookies。对于我刚才读到的内容,似乎默认情况下不会发送cookie。

试试这篇文章$http doesn't send cookie in Requests

更新2

跨域策略可能很麻烦,但它们需要存在才能保护对Web内容的访问。 Java服务器正常运行,正在进行身份验证并正在共享cookie。从一开始,Java服务器一切都很好。

任何中间件技术遇到跨域问题都是一样的。

浏览器阻止了您的应用程序,因为您的客户端域(运行JavaScript的地方)不允许访问Java服务器域。应用程序(您的AngularJS和Java Server)正在不同的域中执行,因此JavaScript调用"在引擎盖下#34;被浏览器阻止。旧的IE版本过去曾经允许使用它。

示例:

  • JavaScript代码从localhost或本地文件系统加载
  • Java Server正在http://192.168.1.15:8080运行(将此替换为您的IP或任何地址)

也许JSONP可以救你:

  

JSONP允许页面通过以下方式接收来自不同域的JSON数据   在页面中添加一个元素,用于加载JSON响应   来自不同域的回调。

对于这两个应用程序,跨域策略将验证:协议主机名端口。如果一个不同,则会发生安全性并且程序失败。

此处有更多信息:Same-origin policy

你的AngularJS也没什么问题。我过去遇到过这种情况,您可以使用普通的Java Script复制它(这是可以适应您问题的功能代码):

function loadXMLDoc() {
    var xmlhttp=new XMLHttpRequest();
    xmlhttp.onreadystatechange=function() {
        if (xmlhttp.readyState==4 && xmlhttp.status==200) {
            document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
        }
    }
    xmlhttp.open("POST","http://192.168.9.117:8080/restful-login-web/rest/loginservice/login",true);
    xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    xmlhttp.send("username=evandro&password=senha123");  
}

以下错误将显示在您的浏览器控制台中:

XMLHttpRequest cannot load http://192.168.9.117:8080/restful-login-web/rest/loginservice/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

GET调用也会发生这种情况。

您可以允许外部应用程序使用JavaScript与设置Access-Control-Allow-Origin的Java服务器进行通信(.header("Access-Control-Allow-Origin", "*")):

return Response.status(Response.Status.OK).header("Access-Control-Allow-Origin", "*").type("text/plain").entity("Login successfull").build();

警告:替换" *"对于运行应用程序客户端的域。

我建议您调查跨域政策主题。如果可以,也许一个简单的解决方案是在Java容器中运行客户端JavaScript。然后两个应用程序将自动在同一个域中。

我的意思是,如果您使用JSP / Servlet发布应用程序客户端Java脚本,那么您就不会遇到此问题。如果您在普通文件中开发JavaScript,只需将它们包装在Java Web应用程序中即可。因为您将执行从" xyz.com"中检索到的Java脚本代码。域,运行在同一个" xyz.com"将允许浏览器交换信息。这将有效。

对不起,我花了更多的时间才意识到你正在对另一个域进行AJAX调用。

如果您需要沟通不同的域(可能服务器是外部服务)并且您无法找到任何帮助,我建议您专门针对跨域问题打开另一个问题。据我所知,这个问题不再与Java服务器本身相关联。

答案 1 :(得分:1)

RESTful服务意味着无状态。需要授权和身份验证的请求会在每个请求上发送身份验证令牌,然后由服务器进行验证。这背后的想法是,给定令牌,您可以从任何客户端(桌面,电话)发出请求以获取资源。这对于第三方集成非常方便,如果您的应用程序将落后于负载平衡器,则必须使用。

这一特定的阅读对于理解有关RESTful服务的一些概念非常有用:

Do sessions really violate RESTfulness?

使用会话时,必须绑定到单个服务器。通过查看您的问题并阅读更多评论,应用程序似乎正在失去与用户连接的会话。