Good morning.
I have a problem when I try to perform logout in the authenticated system via a digital certificate.
To better describe the problem is as follows:
The browser presented the certificates for authentication check box, selecting and providing the PIN for the certificate selected the system performs login normally. The problem is when the user triggers the logout button, it invalidates the session and redirects to the login screen again. However when the user clicks the button that redirects to a restricted area the browser should resubmit the certificate selection box, but the same goes direct, using the certificate information selected in the previous login.
If we stop the server or close and open the browser it will prompt the choice of certificate again.
standalone.xml:
<subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" native="false">
<connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http" redirect-port="8443"/>
<connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https" secure="true">
<ssl key-alias="localhost" verify-client="true"/>
</connector>
<virtual-server name="default-host" enable-welcome-root="true">
<alias name="localhost"/>
<alias name="example.com"/>
</virtual-server>
web.xml:
<filter>
<filter-name>Authentication X509Certificate Filter</filter-name>
<filter-class>br.gov.sp.sefin.desif.security.servlet.AuthX509CertificateFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Authentication X509Certificate Filter</filter-name>
<url-pattern>/pages/*</url-pattern>
</filter-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>pages/*</web-resource-name>
<url-pattern>/pages/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
</login-config>
Filter authentication AuthX509CertificateFilter :
public class AuthX509CertificateFilter implements Filter {
private static final String MS_005 = "MS_005";
private static final String URI_DEFINIR_IF = "/internet/pages/home.xhtml";
private Principal authenticatedUser;
#Inject
private RepresentanteBO representanteBO;
#Inject
private InstituicaoFinanceiraBO instituicaoFinanceiraBO;
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
Object attrSessionValid = req.getSession().getAttribute("sessionValid");
Object attrSessionAuthenticated = req.getSession().getAttribute("authenticated");
Object attrSessionInstituicaoFinanceira = req.getSession().getAttribute("instituicaoFinanceiraInternet");
Boolean sessionValid = (Boolean) (attrSessionValid != null ? attrSessionValid : Boolean.FALSE);
Boolean sessionAuthenticated = (Boolean) (attrSessionAuthenticated != null ? attrSessionAuthenticated : Boolean.FALSE);
if(!sessionValid || (URI_DEFINIR_IF.equals(req.getRequestURI()) && attrSessionInstituicaoFinanceira == null)) {
X509Certificate certs[] = (X509Certificate[] )req.getAttribute("javax.servlet.request.X509Certificate");
if(certs != null) {
X509Certificate t = (X509Certificate) certs[0];
Principal subjectDN = t.getSubjectDN();
authenticatedUser = subjectDN;
sessionAuthenticated = validarAutenticacao(subjectDN, req, resp);
chain.doFilter(new HttpServletRequestWrapper(req) {
#Override
public Principal getUserPrincipal() {
return authenticatedUser;
}
}, response);
}
} else {
Principal userPrincipal = req.getUserPrincipal();
if(userPrincipal != null) {
sessionAuthenticated = validarAutenticacao(userPrincipal, req, resp);
}
chain.doFilter(new HttpServletRequestWrapper(req) {
#Override
public Principal getUserPrincipal() {
return authenticatedUser;
}
}, response);
}
if(!resp.isCommitted() && !sessionAuthenticated) {
Object attribute = req.getSession().getAttribute("cpfCnpj");
if(attribute != null)
req.getSession().setAttribute(MS_005, MessagePtBrUtil.recupera(MS_005, UtilFormatter.formatarCPF((String) attribute)));
RequestDispatcher dispatcher = req.getRequestDispatcher("../login.xhtml");
dispatcher.forward(req, resp);
}
}
public void atualizarDadosDeSessao(HttpServletRequest req, Boolean sessionValid, Boolean sessionAuthenticated) {
req.getSession().setAttribute("sessionValid", sessionValid);
req.getSession().setAttribute("authenticated", sessionAuthenticated);
}
public Boolean validarAutenticacao(Principal userPrincipal, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Boolean sessionValid = Boolean.TRUE;
Boolean sessionAuthenticated = Boolean.TRUE;
String[] cn = userPrincipal.getName().split(",");
String cpfCnpj = cn[0].split(":")[1];
req.getSession().setAttribute("cpfCnpj", cpfCnpj);
BigInteger raizCnpj = new BigInteger(cpfCnpj.substring(0, 8));
if(cpfCnpj.length() == 14 && instituicaoFinanceiraBO.verificarInstituicaoFinanceiraRaizCnpj(raizCnpj)) {
RequestDispatcher dispatcher = req.getRequestDispatcher("../pages/home.xhtml");
dispatcher.forward(req, resp);
} else {
BigInteger cpf = new BigInteger(cpfCnpj);
if(representanteBO.verificarRepresentanteInstituicaoFinanceira(cpf)) {
RequestDispatcher dispatcher = req.getRequestDispatcher("../pages/autenticarusuario/definirInstituicaoFinanceira.xhtml?cpf="+cpf);
dispatcher.forward(req, resp);
} else { // não tem instituição financeira vinculada ao CPF
sessionValid = Boolean.FALSE; sessionAuthenticated = Boolean.FALSE;
}
}
atualizarDadosDeSessao(req, sessionValid, sessionValid);
return sessionValid && sessionAuthenticated;
}
#Override
public void destroy() {
}
}
Logout method:
public void sair() {
ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
this.inserirLogAuditoriaLogout();
context.invalidateSession();
HttpServletRequest request = (HttpServletRequest) context.getRequest();
request.getSession().setAttribute("sessionValid", Boolean.FALSE);
request.getSession().setAttribute("authenticated", Boolean.FALSE);
try {
request.logout();
context.redirect("/internet/login.xhtml");
} catch (IOException e) {
new IOException();
} catch (ServletException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I've tried using some javascript solutions to perform the cleaning of the certificate for authentication data stored in the browser. Example:
window.crypto.logout();
document.execCommand("ClearAuthenticationCache");
function logOut()
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.timeout = 2000; // 2 seconds
xmlHttp.onreadystatechange = function ()
{
if (xmlHttp.readyState == 4)
{
console.log("status: "+xmlHttp.status);
console.log("response: '"+xmlHttp.responseText+"'");
}
};
xmlHttp.open("GET", "/internet/login.xhtml", true);
xmlHttp.send();
}
But did not work.
Please if anyone has been there and succeeded in solve it present your solution.
I hope I can have been clear in the description of the problem. I am available to best describes it.
I thank you so much attention.
Related
I'm currently having trouble regarding the token generated by <protected-views> of JSF.
I added the page I want to protect in faces-config.xml
<protected-views>
<url-pattern>/restricted/account-management/users.xhtml</url-pattern>
<url-pattern>/restricted/account-management/users.jsf</url-pattern>
</protected-views>
Then for example when I go the users page using an <h:link>
<h:link outcome="users" title="View">
<f:param name="user" value="#{e.id}" />
</h:link>
the token generated in the URL is this
/restricted/account-management/users.jsf?javax.faces.Token=OW5KkkfJZrrfmZSXwA%253D%253D&user=4
The page returns a ProtectedViewException
Then I found out that the correct token is actually:
/restricted/account-management/users.jsf?javax.faces.Token=OW5KkkfJZrrfmZSXwA%3D%3D
The token was encoded in the URL, where % became %25. When I copy-paste the correct token into the URL, I get into the users page successfully.
Any help would be appreciated.
This is a problem with the versions 2.2.11 and above of Mojarra JSF Implementation, you can see the details about issue in https://github.com/javaee/javaserverfaces-spec/issues/1161 and here https://github.com/javaserverfaces/mojarra/issues/4139
One of the alternatives to handle the problem is to create a CustomExternalContext to handle the double encoding.
First you need declare in faces-config.xml a CustomExternalContextFactory:
<factory>
<external-context-factory>com.proitc.config.CustomExternalContextFactory</external-context-factory>
</factory>
In the ExternalContextFactory you define the CustomExternalContext:
public class CustomExternalContextFactory extends ExternalContextFactory {
private ExternalContextFactory externalContextFactory;
public CustomExternalContextFactory() {}
public CustomExternalContextFactory(ExternalContextFactory externalContextFactory) {
this.externalContextFactory = externalContextFactory;
}
#Override
public ExternalContext getExternalContext(Object context, Object request, Object response)
throws FacesException {
ExternalContext handler = new CustomExternalContext((ServletContext) context,
(HttpServletRequest) request, (HttpServletResponse) response);
return handler;
}
}
The CustomExternalContext override the methods encodeBookmarkableURL and encodeRedirectURL:
public class CustomExternalContext extends ExternalContextImpl {
public CustomExternalContext(ServletContext sc, ServletRequest request,
ServletResponse response) {
super(sc, request, response);
}
#Override
public String encodeBookmarkableURL(String baseUrl, Map<String, List<String>> parameters) {
FacesContext context = FacesContext.getCurrentInstance();
String encodingFromContext =
(String) context.getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
if (null == encodingFromContext) {
encodingFromContext =
(String) context.getViewRoot().getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
}
String currentResponseEncoding =
(null != encodingFromContext) ? encodingFromContext : getResponseCharacterEncoding();
UrlBuilder builder = new UrlBuilder(baseUrl, currentResponseEncoding);
builder.addParameters(parameters);
String secureUrl = builder.createUrl();
//Handle double encoding
if (parameters.size() > 0 && baseUrl.contains("javax.faces.Token")) {
try {
int beginToken = secureUrl.indexOf("javax.faces.Token");
int endToken = secureUrl.indexOf("&") - 1;
String doubleEncodeToken = secureUrl.substring(beginToken, endToken);
String encodeToken = URLDecoder.decode(doubleEncodeToken, currentResponseEncoding);
secureUrl = secureUrl.replace(doubleEncodeToken, encodeToken);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
return secureUrl;
}
#Override
public String encodeRedirectURL(String baseUrl, Map<String, List<String>> parameters) {
FacesContext context = FacesContext.getCurrentInstance();
String encodingFromContext =
(String) context.getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
if (null == encodingFromContext) {
encodingFromContext =
(String) context.getViewRoot().getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
}
String currentResponseEncoding =
(null != encodingFromContext) ? encodingFromContext : getResponseCharacterEncoding();
UrlBuilder builder = new UrlBuilder(baseUrl, currentResponseEncoding);
builder.addParameters(parameters);
String secureUrl = builder.createUrl();
//Handle double encoding
if (parameters.size() > 0 && baseUrl.contains("javax.faces.Token")) {
try {
int beginToken = secureUrl.indexOf("javax.faces.Token");
int endToken = secureUrl.indexOf("&") - 1;
String doubleEncodeToken = secureUrl.substring(beginToken, endToken);
String encodeToken = URLDecoder.decode(doubleEncodeToken, currentResponseEncoding);
secureUrl = secureUrl.replace(doubleEncodeToken, encodeToken);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
return secureUrl;
}
}
You can find a working example in https://github.com/earth001/jsf-protected-view
I set filename in the HttpServletResponse header but when I download it has not this filename
FileInputStream fis = new FileInputStream(fileDocumento);
PortletResponse portletResponse=(PortletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
HttpServletResponse res = PortalUtil.getHttpServletResponse(portletResponse);
res.setHeader("Content-Disposition", "attachment; filename=schedaObiettivoTAC_.docx");
res.setHeader("Content-Transfer-Encoding", "binary");
res.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
res.flushBuffer();
OutputStream out=res.getOutputStream();
out.write(IOUtils.toByteArray(fis));
out.close();
fis.close();
You should not use the HttpServletResponse. Instead you should create a custom Resource and ResourceHandler:
CustomResourceHandler.java:
public final class CustomResourceHandler extends ResourceHandlerWrapper {
// Public Constants
public static final String LIBRARY_NAME = "exampleLib";
public static final String RESOURCE_NAME = "exampleName";
// Private Data Members
private ResourceHandler wrappedResourceHandler;
public CustomResourceHandler(ResourceHandler resourceHandler) {
this.wrappedResourceHandler = resourceHandler;
}
#Override
public Resource createResource(String resourceName, String libraryName) {
if (LIBRARY_NAME.equals(libraryName)) {
if (RESOURCE_NAME.equals(resourceName)) {
return new CustomResource(libraryName, resourceName,
"exampleFileName.txt", "Example Content");
}
else {
return super.createResource(resourceName, libraryName);
}
}
else {
return super.createResource(resourceName, libraryName);
}
}
#Override
public ResourceHandler getWrapped() {
return wrappedResourceHandler;
}
#Override
public boolean libraryExists(String libraryName) {
if (LIBRARY_NAME.equals(libraryName)) {
return true;
}
else {
return super.libraryExists(libraryName);
}
}
/* package-private */ static final class CustomResource extends Resource {
private final String content;
private final Map<String, String> responseHeaders;
private final String requestPath;
private final URL url;
public CustomResource(String libraryName, String resourceName,
String fileName, String content) {
super.setLibraryName(libraryName);
super.setResourceName(resourceName);
super.setContentType("text/plain");
Map<String, String> responseHeaders = new HashMap<String, String>();
responseHeaders.put("Content-Disposition",
"attachment; filename=" + fileName + ";");
this.responseHeaders = Collections.unmodifiableMap(responseHeaders);
StringBuilder sb = new StringBuilder();
sb.append(ResourceHandler.RESOURCE_IDENTIFIER);
sb.append("/");
sb.append(super.getResourceName());
sb.append("?ln=");
sb.append(super.getLibraryName());
this.requestPath = sb.toString();
URL url;
try {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
url = new URL(externalContext.encodeResourceURL(this.requestPath));
}
catch (MalformedURLException e) {
url = null;
}
this.url = url;
this.content = content;
}
#Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(
content.getBytes(StandardCharsets.UTF_8));
}
#Override
public String getRequestPath() {
return requestPath;
}
#Override
public Map<String, String> getResponseHeaders() {
return responseHeaders;
}
#Override
public URL getURL() {
return url;
}
#Override
public boolean userAgentNeedsUpdate(FacesContext facesContext) {
// Return false if the content cannot change dynamically.
return true;
}
}
}
WEB-INF/faces-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<application>
<!-- ... -->
<resource-handler>custom.resource.handler.CustomResourceHandler</resource-handler>
</application>
<!-- ... -->
</faces-config>
Here's some example code for downloading the resource:
<h:outputLink target="_blank" value="#{bean.getDownloadURL(facesContext)}">
<h:outputText value="download" />
</h:outputLink>
public String getDownloadURL(FacesContext facesContext) {
return facesContext.getApplication().getResourceHandler()
.createResource(CustomResourceHandler.RESOURCE_NAME,
CustomResourceHandler.LIBRARY_NAME)
.getURL().toString();
}
You can also look at the Liferay Faces JSF Export PDF for a full portlet example to download/export a file.
If you are in the action or render phase of your portlet (what I would guess for a JSF portlet): there is a ResponseWrapper which will suppress any header. I'm using this method to find the response for sending binary data during the JSF lifecycle:
public static HttpServletResponse getHttpServletResponse() {
final FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext == null) {
throw new IllegalStateException("Not inside a JSF request");
}
final Object responseObject = facesContext.getExternalContext().getResponse();
if (responseObject instanceof HttpServletResponse) {
return (HttpServletResponse) responseObject;
}
if (responseObject instanceof PortletResponse) {
// Use Liferays util to find the real response
HttpServletResponse response = PortalUtil.getHttpServletResponse((PortletResponse) responseObject);
// Find the outer most response (setting the headers would have no effect, as we are included)
while (response instanceof ServletResponseWrapper) {
final ServletResponse servletResponse = ((ServletResponseWrapper) response).getResponse();
if (!(servletResponse instanceof HttpServletResponse)) {
break;
}
response = (HttpServletResponse) servletResponse;
}
return response;
}
throw new IllegalStateException("Unknown type of response object: " + responseObject);
}
Good Day!
Im having a problem with my log in in JSF, it seems that after the log in, the session becomes null. It logs me in the first, but when i hit refresh or go to another page it redirects to login. Hope anybody can help with this. Below are my codes.
Thanks
Filter Class:
#Override
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest request = (HttpServletRequest) arg0;
HttpSession session = request.getSession();
User user = (session != null) ? (User) session.getAttribute("userBean") : null;
if(user != null){
arg2.doFilter(arg0, arg1);
}else{
HttpServletResponse response = (HttpServletResponse) arg1;
response.sendRedirect(request.getContextPath() + "/login.xhtml");
}
}
Login from User Managed Bean Class:
public void login(){
UserDAO action = new UserDAO();
try{
User u = action.login(username, password);
if(u == null){
FacesContext.getCurrentInstance().getExternalContext().redirect(showLogin() + ".xhtml?ref=err");
}else{
FacesContext.getCurrentInstance().getExternalContext().getSession(true);
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("userBean", u);
FacesContext.getCurrentInstance().getExternalContext().redirect("pages/dashboard.xhtml");
}
}catch(Exception e){
e.printStackTrace();
}
}
My web.xml:
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>rpt.filters.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/pages/*</url-pattern>
</filter-mapping>
I've tried to make autorisation form by using jsf 1.2 but I had some exceptions with redirect.
Bean code
public class UserAutorisationBean implements Serializable {
private Boolean isLogin = false;
private String login = "";
private String password = "";
public void autoriseLoginAndPass() throws IOException {
if (this.login == "user" && this.password == "password") {
this.isLogin = true;
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response =
(HttpServletResponse) context.getExternalContext().getResponse();
response.sendRedirect("web/HelloWorld.jsp");
} else {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response =
(HttpServletResponse) context.getExternalContext().getResponse();
response.sendRedirect("web/Error.jsp");
}
}
Filter code
public class Filter implements javax.servlet.Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpSession session = null;
session = httpRequest.getSession(false);
if (session != null) {
UserAutorisationBean userAutorisationBean = null;
userAutorisationBean =
(UserAutorisationBean) session.getAttribute("userautorisationbean");
if (userAutorisationBean != null) {
if (!userAutorisationBean.isLoginIn()) {
httpResponse.sendRedirect(httpRequest.getContextPath() + "/Error.jsp");
}
}
chain.doFilter(request, response);
}
if (session == null) {
httpResponse.sendRedirect(httpRequest.getContextPath() + "/Error.jsp");
}
}
public void destroy() {
}
}
Stack:
message Cannot forward after response has been committed
description The server encountered an internal error that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: Cannot forward after response has been committed
javax.faces.webapp.FacesServlet.service(FacesServlet.java:256)
root cause
java.lang.IllegalStateException: Cannot forward after response has been committed
com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:414)
com.sun.faces.application.ViewHandlerImpl.executePageToBuildView(ViewHandlerImpl.java:455)
com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:139)
com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:108)
com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:266)
com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:159)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:245)
I've tried to find some advices by using search but it didn't help me to solve the problem.
I use Orchestra and RichFaces in my application. When accessing a page in my application I get the following error many times and the page doesn't load:
WARN _ReentrantLock:103 - Waited for longer than 30000 milliseconds for access to lock org.apache.myfaces.orchestra.lib._ReentrantLock#78214f6b which is locked by thread http-8080-2
I believe at the heart the problem is a filter that I use for authentication. Here is its code (conversationController is a conversation scoped bean):
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
FacesContextBuilder builder = new FacesContextBuilder();
FacesContext facesContext = builder.getFacesContext(request, response);
ServletContext servletContext = (ServletContext) facesContext.getExternalContext().getContext();
Application application = facesContext.getApplication();
ELContext elContext = facesContext.getELContext();
ConversationController conversationController = (ConversationController) application.getELResolver().getValue(elContext, null, "conversationController");
SessionController sessionController = (SessionController) application.getELResolver().getValue(elContext, null, "sessionController");
ApplicationController applicationController = (ApplicationController) application.getELResolver().getValue(elContext, null, "applicationController");
EntityRegistry entityRegistry = conversationController.getEntityRegistry();
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse= (HttpServletResponse) response;
User currentUser = sessionController.getCurrentUser();
Boolean isTesting = (Boolean) servletContext.getAttribute("ginger.TESTING");
if (isTesting == null) isTesting = false;
if (currentUser == null)
{
if (httpRequest.isSecure() || isTesting)
{
Cookie[] cookies = httpRequest.getCookies();
Cookie cookie = null;
if (cookies != null)
{
for (int i=0; i<cookies.length; i++)
{
if (cookies[i].getName().equals("ginger.USERCOOKIE"))
{
cookie = cookies[i];
break;
}
}
}
if (cookie != null)
{
currentUser = entityRegistry.getUserByCookie(cookie.getValue());
}
if (currentUser == null)
{
currentUser = new UnregisteredUser();
String cookieValue = String.valueOf(applicationController.getRandom());
currentUser.setCookie(cookieValue);
entityRegistry.storeUser(currentUser);
cookie = new Cookie("ginger.USERCOOKIE", cookieValue);
cookie.setPath(applicationController.getPath());
cookie.setMaxAge(365*24*60*60);
if (!isTesting) cookie.setSecure(true);
httpResponse.addCookie(cookie);
}
sessionController.setCurrentUser(currentUser);
#SuppressWarnings("unchecked")
String url = URLConstructor.constructUrl(servletContext, httpRequest, httpResponse, false, httpRequest.getRequestURI(), httpRequest.getParameterMap());
httpResponse.sendRedirect(url);
}
else
{
#SuppressWarnings("unchecked")
String url = URLConstructor.constructUrl(servletContext, httpRequest, httpResponse, true, httpRequest.getRequestURI(), httpRequest.getParameterMap());
httpResponse.sendRedirect(url);
}
}
else
{
chain.doFilter(request, response);
}
builder.removeFacesContext();
}
I solved this by releasing the FacesContext before the response is committed. Like this:
#SuppressWarnings("unchecked")
String url = URLConstructor.constructUrl(servletContext, httpRequest, httpResponse, true, httpRequest.getRequestURI(), httpRequest.getParameterMap());
builder.removeFacesContext();
httpResponse.sendRedirect(url);
I don't understand this completely but it seems that the new request was still using the old FacesContext and this interfered with the _ReentrantLock getting unlocked.