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.
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
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.
while logout i did removed session object and invalidated session also as like below
public String logout() throws IOException {
logger.info("logout() : satarted----- ");
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.getSessionMap().remove("visitorComponent");
System.out.println("*************_->"+ec.getSessionMap().remove("visitorComponent"));
ec.invalidateSession();
ec.redirect(ec.getRequestContextPath() + "/logout.xhtml");
return null;
// return "logout?faces-redirect=true";
}
But still in filter class its giving values, filter class code like below
public class AuthorizationFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession();
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("Cache-Control", "no-cache,no-store,must-revalidate"); // HTTP 1.1
httpResponse.setHeader("Pragma", "no-cache"); // HTTP 1.0
httpResponse.setDateHeader("Expires", 0);
if (session.getAttribute("visitorComponent") != null) {
System.out.println("-sdf>"+((VisitorComponent) session.getAttribute("visitorComponent")).getAdmin());
}
System.out.println("->"+session.getAttribute("visitorComponent"));
System.out.println("=url>"+req.getRequestURI());
System.out.println("=>"+req.getRequestURI().endsWith("login.xhtml"));
if (session.getAttribute("visitorComponent") != null || req.getRequestURI().endsWith("index.xhtml")) {
chain.doFilter(request, httpResponse);
} else {
System.out.println("---in else--");
// HttpServletResponse res = (HttpServletResponse) response;
httpResponse.sendRedirect("index.xhtml");
return;
}
}
Could you please help any one, what I need to do?
Finally I found solution but side effects are there.
My solution is, previously I was not kept login object manually because my login class in session scope. If i do in this way its not clear the object after invalidate also because while starting application login class instantiated.
#ManagedBean(name = "visitorComponent")
#SessionScoped
public class VisitorComponent {
Admin admin = new Admin();
public String login() {
// some code to verify login details
this.admin = adminService.getAdminObject(adminId);
}
Now i did manually by get session object map and put my login object in session map.
#ManagedBean(name = "visitorComponent")
#SessionScoped
public class VisitorComponent {
Admin admin = new Admin();
public String login() {
// some code to verify login details
this.admin = adminService.getAdminObject(adminId);
// Session object creating to get the session values
ExternalContext externalContext = FacesContext.getCurrentInstance()
.getExternalContext();
Map<String, Object> sessionMap = externalContext.getSessionMap();
sessionMap.put("abcadminBean", this.admin);
}
Now its working fine by invalidate but problem is in my login page
i have
I have doubt in my filterclass, that is like below
public class AuthorizationFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession();
if (session.getAttribute("abcadminBean") != null || req.getRequestURI().endsWith("index.xhtml")) {
chain.doFilter(request, response);
} else {
FacesContext fc = FacesContext.getCurrentInstance();
if (fc == null) {
// Create new Lifecycle.
LifecycleFactory lifecycleFactory = (LifecycleFactory)
FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
// Create new FacesContext.
FacesContextFactory contextFactory = (FacesContextFactory)
FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
fc = contextFactory.getFacesContext(
((HttpServletRequest) request).getSession().getServletContext(), request, response, lifecycle);
}
System.out.println("fc->"+fc);
ExternalContext ec = fc.getExternalContext();
ec.redirect(ec.getRequestContextPath() + "/index.xhtml");
// HttpServletResponse res = (HttpServletResponse) response;
// ((HttpServletResponse) response).sendRedirect("index.xhtml");
return;
}
}
Here I am redirecting my page, I thought it is the problem
Could you please any one help me, What i need to do for my UI changes ?
Finally I caught solution.
Why because it is not loading all primefaces UI effects is,
For every request our filter is checking so in Filter class we have to write condition to allow our CSS and JS file as like below
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession();
if (session.getAttribute("loginDetails") != null
|| session.getAttribute("empLoginDetails") != null
|| req.getRequestURI().endsWith("index.xhtml")
|| req.getRequestURI().endsWith("forgetpass.xhtml")
|| req.getRequestURI().endsWith("empLogin.xhtml")
|| req.getRequestURI().endsWith("logout.xhtml")
|| req.getRequestURI().endsWith("ajax-loader.gif.xhtml")
|| req.getRequestURI().contains(".js")
|| req.getRequestURI().contains(".css")) {
chain.doFilter(request, response);
} else {
FacesContext fc = FacesContext.getCurrentInstance();
if (fc == null) {
// Create new Lifecycle.
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle = lifecycleFactory
.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
// Create new FacesContext.
FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder
.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
fc = contextFactory.getFacesContext(
((HttpServletRequest) request).getSession()
.getServletContext(), request, response,
lifecycle);
}
RequestDispatcher dispatcher = request
.getRequestDispatcher("/index.xhtml");
dispatcher.forward(request, response);
return;
}
Now my application is working fine with filter class
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 try to create login form in web application.
in JSP page I can use
<%
String name = request.getParameter( "username" );
session.setAttribute( "theName", name );
%>
but now I am using JSF /Facelets for web application
I don't know how to create session in JSF Backing bean for client and check if user is logged in or not so it will redirect into login page.
who can help me give me link tutorial for these problem ?
thank you before
Now I have little problem with mapping into web.xml
code snipped of class Filter
#Override
public void init(FilterConfig filterConfig) throws ServletException {
this.config = filterConfig;
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
LoginController controller = (LoginController) req.getSession()
.getAttribute("loginController");
if (controller == null || !controller.isLoggedIn()) {
res.sendRedirect("../admin/login.xhtml");
} else {
chain.doFilter(request, response);
}
}
and in web.xml I map with <fitler> tag
<filter>
<filter-name>userLoginFilter</filter-name>
<filter-class>com.mcgraw.controller.UserLoginFilter</filter-class>
<init-param>
<param-name>loginPage</param-name>
<param-value>/login.xhtml</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>userLoginFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
I have one folder admin in web project and I check if the user is not logged in with admin permission to not access page (I can do the permission check) but when I use the filter the browser doesn't understand url ??
no StackTrace show when the browser doesn't understand url
Error shown on Firefox
The page isn't redirecting properly
on IE it loading ... loading . .. non-stop
now I change condition which check if req.getPathInfo.startsWith("/login.xhtml") it will do chain
I have 2 idea but it response 500 HTTP STATUS
if (controller == null || !controller.isLoggedIn()) {
res.sendRedirect("../admin/login.xhtml");
if(req.getPathInfo().startsWith("/login.xhtml")){
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
===============
if (controller == null || !controller.isLoggedIn()) {
if (!req.getPathInfo().startsWith("/login.xhtml")) {
res.sendRedirect("../admin/login.xhtml");
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
======================
update Class loginController
package com.mcgraw.controller;
import com.DAO.UserBean;
import com.entity.IUser;
import java.io.Serializable;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
/**
* #author Kency
*/
#ManagedBean
#SessionScoped
public class LoginController implements Serializable {
#EJB
private UserBean userBean;
private IUser user;
private boolean admin;
private boolean mod;
private PasswordService md5;
/** Creates a new instance of LoginController */
public LoginController() {
user = new IUser();
md5 = new PasswordService();
}
// getter / setter
public boolean isMod() {
return mod;
}
public void setMod(boolean mod) {
this.mod = mod;
}
public IUser getUser() {
return user;
}
public void setUser(IUser user) {
this.user = user;
}
public boolean isAdmin() {
return admin;
}
public void setAdmin(boolean admin) {
this.admin = admin;
}
public String cplogin() {
String md5Password = md5.md5Password(user.getPassword());
if (userBean.userLogin(user.getUsername(), md5Password) != null) {
if (user.getUsername() != null || md5Password != null) {
user = userBean.userLogin(user.getUsername(), md5Password);
if (user.getGroups().getAdmin() != null) {
setAdmin(user.getGroups().getAdmin());
}
if (user.getGroups().getMods() != null) {
setMod(user.getGroups().getMods());
}
if (isAdmin() == true || isMod() == true) {
return "home";
} else {
return "login";
}
} else {
return "login";
}
} else {
return "login";
}
}
public String logout() {
user = null;
return "login";
}
public boolean isLoggedIn() {
return user != null;
}
}
I have new problem if render JSF taglib with method loggedIn, in index page (not in admin folder) user doesn't login can see what I render example, <== this like if user doesn't login user can't see but why can he see it?
You can in JSF get/set HTTP session attributes via ExternalContext#getSessionMap() which is basically a wrapper around HttpSession#get/setAttribute().
#Named
#RequestScoped
public class LoginController {
private String username;
private String password;
#EJB
private UserService userService;
public String login() {
User user = userService.find(username, password);
FacesContext context = FacesContext.getCurrentInstance();
if (user == null) {
context.addMessage(null, new FacesMessage("Unknown login, try again"));
username = null;
password = null;
return null;
} else {
context.getExternalContext().getSessionMap().put("user", user);
return "userhome?faces-redirect=true";
}
}
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "index?faces-redirect=true";
}
// ...
}
In the Facelets page, just bind the username and password input fields to this bean and invoke login() action accordingly.
<h:form>
<h:inputText value="#{loginController.username}" />
<h:inputSecret value="#{loginController.password}" />
<h:commandButton value="login" action="#{loginController.login}" />
</h:form>
Session attributes are directly accessible in EL. A session attribute with name user is in EL available as #{user}. When testing if the user is logged in some rendered attribute, just check if it's empty or not.
<h:panelGroup rendered="#{not empty user}">
<p>Welcome, #{user.fullName}</p>
<h:form>
<h:commandButton value="logout" action="#{loginController.logout}" />
</h:form>
</h:panelGroup>
The logout action basically just trashes the session.
As to checking an incoming request if a user is logged in or not, just create a Filter which does roughly the following in doFilter() method:
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String loginURI = request.getContextPath() + "/login.xhtml";
boolean loggedIn = session != null && session.getAttribute("user") != null;
boolean loginRequest = request.getRequestURI().equals(loginURI);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER);
if (loggedIn || loginRequest || resourceRequest) {
chain.doFilter(request, response);
} else {
response.sendRedirect(loginURI);
}
}
Map it on an url-pattern covering the restricted pages, e.g. /secured/*, /app/*, etc.
See also:
How to handle authentication/authorization with users in a database?
Authorization redirect on session expiration does not work on submitting a JSF form, page stays the same
Try this in your backing bean when a request is received (like in an action method):
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpSession session = request.getSession();
Then you can work with the request and session objects just like you used to with JSPs, setting attributes and so on.
You might also want to take a look at my related question about checking the client session in a servlet Filter. You could write a similar Filter to check for the user login in their HttpSession and then do a redirect (or RequestDispatch like I ended up doing) to your login page if needed.