How do a web filter in JSF 2? - jsf

I create this filter :
public class LoginFilter 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("authenticated") != null || req.getRequestURI().endsWith("login.xhtml")) {
chain.doFilter(request, response);
} else {
HttpServletResponse res = (HttpServletResponse) response;
res.sendRedirect("login.xhtml");
return;
}
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void destroy() {
}
}
This is my structure:
And then I add the filter in the web.xml:
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
The filter works as it should but keeps giving me this error:
"Was not possible find or provider the resource, login"
And after that my richfaces doesn't works anymore.
How can I solve that ? Or create a web filter correctly ?

Any path-relative URL (i.e. URLs which do not start with /) which you pass to sendRedirect() will be relative to the current request URI. I understand that the login page is at http://localhost:8080/contextname/login.xhtml. So, if you for example access http://localhost:8080/contextname/pages/user/some.xhtml, then this redirect call will actually point to http://localhost:8080/contextname/pages/user/login.xhtml, which I think don't exist. Look at the URL in your browser address bar once again.
To fix this problem, rather redirect to a domain-relative URL instead, i.e. start the URL with /.
res.sendRedirect(req.getContextPath() + "/login.xhtml");

Related

Why is it invalid for filter to set Chinese encoding for all web pages?

Recently, I encountered a problem when I learn web filter. I set the filter in web.xml to operate on all web pages. The settings are as follows
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
You can see that all web pages are set to be filtered here.
The function of this filter is to make the web page use gb2312 encoding, the code is as follows:
#WebFilter(filterName = "EncodingFilter")
public class EncodingFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
request.setCharacterEncoding("gb2312");
chain.doFilter(request, response);
}
}
The test servlet is as follows
#WebServlet(name = "DealWithServlet", value = "/DealWithServlet")
public class DealWithServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
// print chinese characters
out.println("word is " + "单词");
}
}
the setting in web.xml are as follows:
<servlet>
<servlet-name>DealWithServlet</servlet-name>
<servlet-class>Servlet.DealWithServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DealWithServlet</servlet-name>
<url-pattern>/Servlet/DealWithServlet</url-pattern>
</servlet-mapping>
configuration are as follows:
configuration
The project structure is as follows:
servlet_demo2
src
filter
EncodingFilter.class
Servlet
DealWithServlet.class
Then I entered the relevant webpage and found that it cannot display Chinese. What is going on here? The address entered is
http://localhost:8088/servlet_demo2/Servlet/DealWithServlet
The actual effect is as follows:actual effect
Could anyone possibly tell me how i can solve this problem?
i forget to add
response.setCharacterEncoding("gb2312");
in EncodingFilter.class.
Add this code, the servlet can display Chinese normally

java.lang.NullPointerException at org.primefaces.util.ResourceUtils.getComponentResources

I have a Spring + JSP application (MyFaces + PrimeFaces) and I've added a filter to it in order to add the same headers to all responses.
The application is working fine but if I restart the server and someone has an open page (with a now invalid or non-existing session) I start getting NullPointerException all the time, but it's happening outside of my code. How can I fix this?
The problem seems to be in org.primefaces.util.ResourceUtils:66 (getComponentResources(FacesContext context)) where it tries this:
List<UIComponent> resources = context.getViewRoot().getComponentResources(context, "head");
But context.getViewRoot() returns null so it fails.
If the client reloads the page, he is redirected to the login page correctly, a new session is created, and errors stop.
NoCacheFilter class:
#WebFilter(servletNames = { "Faces Servlet" })
public class NoCacheFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
// Skip JSF resources (CSS/JS/Images/etc)
if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) {
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
res.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(req, res);
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void destroy() {
}
}
Exception Trace:
java.lang.NullPointerException
at org.primefaces.util.ResourceUtils.getComponentResources(ResourceUtils.java:66)
at org.primefaces.context.PrimePartialResponseWriter.startMetadataIfNecessary(PrimePartialResponseWriter.java:280)
at org.primefaces.context.PrimePartialResponseWriter.startError(PrimePartialResponseWriter.java:107)
at org.apache.myfaces.shared.context.AjaxExceptionHandlerImpl.renderAjaxError(AjaxExceptionHandlerImpl.java:274)
at org.apache.myfaces.shared.context.AjaxExceptionHandlerImpl.handle(AjaxExceptionHandlerImpl.java:238)
at javax.faces.context.ExceptionHandlerWrapper.handle(ExceptionHandlerWrapper.java:61)
at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:217)
at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:143)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:198)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at eu.calabacin.controller.NoCacheFilter.doFilter(NoCacheFilter.java:30)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at eu.calabacin.controller.GlobalFilter.doFilter(GlobalFilter.java:31)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1502)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1458)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Section of web.xml where GlobalFilter is defined:
<filter>
<filter-name>GlobalFilter</filter-name>
<filter-class>eu.calabacin.controller.GlobalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>GlobalFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
GlobalFilter class:
public class GlobalFilter implements Filter {
private final static String LOGIN_PAGE = "/" + GlobalService.LOGIN_PAGE + ".xhtml";
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpSession session = ((HttpServletRequest) request).getSession(false);// don't create a session if there isn't one
if (session != null && !session.isNew()) {
chain.doFilter(request, response);
} else {
redirectToLogin(request, response, chain);
}
}
private void redirectToLogin(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String pathInfo = httpRequest.getServletPath();
if (pathInfo == null || !pathInfo.equalsIgnoreCase(LOGIN_PAGE)) {
String newUrl = httpRequest.getContextPath() + LOGIN_PAGE;
httpResponse.sendRedirect(newUrl);
} else {
chain.doFilter(request, response);
}
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void destroy() {
}
}
Software versions:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring.version>4.2.0.RELEASE</spring.version>
<myfaces.version>2.2.8</myfaces.version>
<primefaces.version>6.0</primefaces.version>
<hibernate.version>5.0.0.Final</hibernate.version>
</properties>
I guess I could 'fix' the problem by changing the ResourceUtils class checking if context.getViewRoot() returns null before trying to use it, but I'm sure I must be doing something wrong somewhere that causes this to fail.
Anyone knows what I'm doing wrong or how I could fix this?
Thank you.
Today I ran into a similar problem (having a NullPointerException exactly at the same PrimeFaces line).
I solved the problem upgrading from Primefaces 6.0 to Primefaces 6.1 and correcting a wrong JPA query that was causing a previous exception (I'm not completely sure which action solved the problem, but I guess it was the upgrade).

When I refresh the page after login+redirect, it redirects me to login page again

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>

Prevent JSF action method execution after a filter redirect

I have implemented a Servlet Filter to do my system's authorization and where needed I redirect the user using this:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
...
if(!isLoggedIn(currentUser)){
if(isSecurePage(requestedPage)){
redirectUser(resp,USER_LOGIN_PAGE);
}
else{ // Carry on
chain.doFilter(request,response);
}
}
else{
if(!isSecurePage(requestedPage)){
redirectUser(resp,USER_WELCOME_PAGE);
}
else if(!canAccess(currentUser,requestedPage)){
redirectUser(resp,req.getContextPath() + USER_DENIED_PAGE);
}
else{ // Carry on
chain.doFilter(request,response);
}
}
}
private void redirectUser(HttpServletResponse response, String page) throws IOException {
response.sendRedirect(page);
}
The redirect happens correctly. My issue is that although ACCESS_DENIED_PAGE is displayed, the JSF action method behind the original request is still executed (a FacesMessage that it creates is displayed in the ACCESS_DENIED_PAGE, for example).
How to prevent this?

How to redirect to another page when already authenticated user accesses login page

I was wondering if it was possible to redirect users if a certain c:if clausule is true?
<c:if test="#{loginController.authenticated}">
//redirect to index page
</c:if>
Yes it is possible.
But, I would suggest you to apply filter for /login.jsp and in the filter forward to the other page if the user has already logged in.
Here is the example which tells how to do this using filter:
public class LoginPageFilter implements Filter
{
public void init(FilterConfig filterConfig) throws ServletException
{
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
{
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if(request.getUserPrincipal() != null){ //If user is already authenticated
response.sendRedirect("/index.jsp");// or, forward using RequestDispatcher
} else{
filterChain.doFilter(servletRequest, servletResponse);
}
}
public void destroy()
{
}
}
Add this filter enty in the web.xml
<filter>
<filter-name>LoginPageFilter</filter-name>
<filter-class>
com.sample.LoginPageFilter
</filter-class>
<init-param>
<param-name>test-param</param-name>
<param-value>This parameter is for testing.</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LoginPageFilter</filter-name>
<url-pattern>/login.jsp</url-pattern>
</filter-mapping>
Apart from the Filter approach, you can also use <f:event type="preRenderView">. Put this somewhere in top of the view:
<f:event type="preRenderView" listener="#{loginController.checkAuthentication}" />
And add this listener method to the LoginController:
public void checkAuthentication() throws IOException {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
if (externalContext.getUserPrincipal() != null) {
externalContext.redirect(externalContext.getRequestContextPath() + "/index.xhtml");
}
}
That's all.
See also:
Is there any easy way to preprocess and redirect GET requests?

Resources