从JSF页面使用jQuery调用RESTAPI,并在没有cookie的情况下获取当前会话
我有一个web应用程序,它使用JSF2.3作为前端,还提供一个API,前端使用Jersey 2.29.1在Tomcat 9服务器上运行 前端提供了一个登录名,该登录名将认证用户存储在从JSF页面使用jQuery调用RESTAPI,并在没有cookie的情况下获取当前会话,jsf,urlencode,jsessionid,Jsf,Urlencode,Jsessionid,我有一个web应用程序,它使用JSF2.3作为前端,还提供一个API,前端使用Jersey 2.29.1在Tomcat 9服务器上运行 前端提供了一个登录名,该登录名将认证用户存储在@SessionScopedAuthenticationBean中。只有当用户在前端登录时,API方法才可以使用 @Path(“/service”) 公共服务{ @得到 @路径(“/data”) @产生(MediaType.APPLICATION_JSON) 公共字符串loadData(){ final Authen
@SessionScoped
AuthenticationBean
中。只有当用户在前端登录时,API方法才可以使用
@Path(“/service”)
公共服务{
@得到
@路径(“/data”)
@产生(MediaType.APPLICATION_JSON)
公共字符串loadData(){
final AuthenticationBean authBean=CDI.current().select(AuthenticationBean.class.get();
if(authBean!=null&&authBean.isLoggedIn(){
//做生意逻辑
}
否则{
抛出新的WebApplicationException(Response.Status.UNAUTHORIZED);
}
}
}
在JSF页面上,API使用“基本”jQuery AJAX调用$.AJAX()
,并根据JSON响应更新一些可视内容。我传递给AJAX调用的URL是“#{request.contextPath}/api/service/data”
一切正常,直到我禁用浏览器中的cookies。如果禁用了cookie,则servlet引擎会将会话ID添加到URL(而不是存储在会话cookie中)。因此,如果我没有显式地将会话ID附加到AJAX调用的URL,我就无法访问API服务方法中的当前会话,例如,“#{request.contextPath}/API/service/data;jsessionid=#{session.ID}”
,因此我无法检查用户是否登录
现在我的问题是,我是否必须为每个AJAX请求手动添加jsessionid
,或者是否有其他“干净”的可能性将会话ID传递给服务方法?或者我必须在API服务中以任何其他方式访问会话吗
。。。将会话ID显式附加到URL
这项任务正是要完成的,另请参见javadoc(emphasis mine):
通过包含会话ID对指定的URL进行编码,或者,如果不需要编码,则返回未更改的URL此方法的实现包括确定会话ID是否需要在URL中编码的逻辑。例如,如果浏览器支持Cookie,或者会话跟踪已关闭,则不需要URL编码
因此,基本上:
#{request.contextPath}#{response.encodeURL('/api/service/data')}
同样的方法是通过委托的方式
在执行所需的任何重写以确保正确标识当前应用程序中的可寻址资源后,返回输入URL
雅加达Servlet:这必须是javax.Servlet.http.HttpServletResponse
方法encodeURL(url)
返回的值
所以,从技术上来说,你也可以这样做
#{request.contextPath}#{facesContext.externalContext.encodeResourceURL('/api/service/data')}
但这样打字就不太方便了。此外,使用{request.contextPath}
已经表明您在servlet之上使用的是JSF,而不是portlet,因此使用{response}
应该很好。您可能希望通过在应用程序范围的bean中定义一个自定义实用程序方法来缩短它。例如
#{functions.encodeURL('/api/service/data')}
。。。将会话ID显式附加到URL
这项任务正是要完成的,另请参见javadoc(emphasis mine):
通过包含会话ID对指定的URL进行编码,或者,如果不需要编码,则返回未更改的URL此方法的实现包括确定会话ID是否需要在URL中编码的逻辑。例如,如果浏览器支持Cookie,或者会话跟踪已关闭,则不需要URL编码
因此,基本上:
#{request.contextPath}#{response.encodeURL('/api/service/data')}
同样的方法是通过委托的方式
在执行所需的任何重写以确保正确标识当前应用程序中的可寻址资源后,返回输入URL
雅加达Servlet:这必须是javax.Servlet.http.HttpServletResponse
方法encodeURL(url)
返回的值
所以,从技术上来说,你也可以这样做
#{request.contextPath}#{facesContext.externalContext.encodeResourceURL('/api/service/data')}
但这样打字就不太方便了。此外,使用{request.contextPath}
已经表明您在servlet之上使用的是JSF,而不是portlet,因此使用{response}
应该很好。您可能希望通过在应用程序范围的bean中定义一个自定义实用程序方法来缩短它。例如
#{functions.encodeURL('/api/service/data')}
这个“答案”并不是对您真正问题的回答,而是解释了为什么这与JSF没有任何关系(尽管最后有一个答案的提示) JSF是一个api,Jersey是一个api(JAX-RS)的实现。它们实际上是互补技术,彼此之间没有任何关系。这就像问我是否可以在一个应用程序中使用JPA和Jersey一样。您的实际问题与JSF Whatshover没有任何关系。与jax-rs一样,JSF使用servlet引擎提供的会话机制 第二件不清楚的事情是你对“前端”的定义是什么,你在哪里运行什么。JavaEE“堆栈”中的JSF是一种前端技术。JSF有一个服务器端部分,您可以在其中声明组件(请参阅),当生成html时,它们有客户端html/javascript/css对应项,它们以JSF规范中指定的方式与服务器进行通信。如果服务器上没有调用服务的“粘合逻辑”的支持,JSF“组件”本身不会起任何作用(请参阅) 现在可能已经很清楚了 JSF组件是否可能通过AJAX调用调用Jersey服务 是“模糊”的,很可能是因为您不了解JSF是什么/做什么以及Jersey如何适应(Jersey在这里应该是“rest”,如果您指的是api,则应该是jax rs),另请参见
- 客户端JSF组件的html部分在JSF spe中与服务器通信