Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java getUserPrincipal返回null_Java_Angularjs - Fatal编程技术网

Java getUserPrincipal返回null

Java getUserPrincipal返回null,java,angularjs,Java,Angularjs,我使用AngularJS作为前端,使用JavaEE作为后端。 我使用RESTful服务创建了两种登录和注销方法: @POST @Path("login") @Produces("application/json") public Response login(@Context HttpServletRequest req, UserTable user) { if (req.getUserPrincipal() == null) { try { r

我使用AngularJS作为前端,使用JavaEE作为后端。 我使用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。我做错了什么?

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

这篇文章对于理解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会话

您可以通过调用
HttpServletRequest.getSession()
方法来实现这一点,如下所示:

req.getSession(true); // Creates a new HTTP Session BEFORE the login.
req.login(user.getUsername(), user.getPassword());
确保服务器在响应中返回JSESSIONID cookie。之后,浏览器将处理它并将其发送到服务器,而您无需担心它或自己处理它

来自登录的响应

请求进一步呼叫(服务呼叫、检查登录、注销等)

更新 也许你需要告诉AngularJS把饼干送来。就我刚才读到的内容而言,默认设置似乎不是发送cookies

试试这个帖子

更新2 跨域策略可能是一个难题,但它们必须存在,才能确保对web内容的访问安全。Java服务器运行正常,正在进行身份验证,并且正在共享cookie。Java服务器从一开始就很好

当涉及到跨域时,任何中间件技术的问题都是一样的

浏览器正在阻止您的应用程序,因为不允许您的客户端域(运行JavaScript的地方)访问Java服务器域。应用程序(AngularJS和Java服务器)在不同的域中执行,因此浏览器会阻止“隐藏”的JavaScript调用。旧的IE版本在过去允许它

例如:

  • JavaScript代码从本地主机或本地文件系统加载
  • Java服务器正在运行(将此替换为您的IP或任何地址)
也许可以救你:

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

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

更多信息请点击此处:

你的AngularJS也没有问题。我在过去遇到过这种情况,您可以使用纯Java脚本复制它(这是可以适应您的问题的功能代码):

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

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与Java服务器进行通信,设置如下(
.header(“Access Control allow Origin”,“*”)
)的
访问控制允许原点:

警告:为运行应用程序客户端的域替换“*”

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

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

很抱歉,我花了太多时间才意识到您正在对另一个域进行AJAX调用


如果您需要与不同的域进行通信(可能服务器是一个外部服务),但找不到任何帮助,我建议您针对跨域问题专门提出另一个问题。据我所知,这个问题已不再与Java服务器本身有关。

听起来问题似乎在您的服务器端。设置一些断点以查看所采用的路径,并沿途检查数据。如果您在注销后再次尝试登录,getUserPrincipal将始终为null,因为用户未经过身份验证。这就是方法req.logout()所做的。@rahpuser我尝试过使用login方法,但没有注销,我第二次使用了它,但是第二次,getUserPrincipal()等于null。Cookie是否在交互过程中保留?@SoluableNonagon我已经这样做了。我试着写这样的东西:Principal p=req.getUserPrincipal();在登录和注销方法中。每次“p”等于null时,服务器都已成功返回JSESSIONID(如第一个屏幕截图中所示)。然而,当我调用logout时,getUserPrincipal()仍然有nullvalue@YanIvanEvdokimov在登录中收到JSSessionID cookie后,是否在注销请求中发送了它?不幸的是,没有。它看起来像在您的屏幕截图中,但没有cookietab@YanIvanEvdokimov检查我的更新。我正在考试
return Response.status(Response.Status.OK).header("Access-Control-Allow-Origin", "*").type("text/plain").entity("Login successfull").build();