JSF ajax request calls filter (should be ignored!) - ajax

I have some filters, which grab e.g. a parameter like "id" to check some right (used to load some contents). These filters should ignore all ajax-requests, because e.g. the rights does not have to be checked after every little request (only on page load)
The Problem is, that when I perform an ajax-request, it throws me a null-pointer, because I don't append the ID with ajax requests. I found out, that it still works, when I use and it fails, when I use (both perform ajax requests).
This is my filter:
public class ExtendedAccessFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
//ignore filter if it is an ajax-request (DOES NOT WORK if not p:commandButton!)
if(isAJAXRequest(req)){
chain.doFilter(request, response);
System.out.println("ABORT FILTER, AJAX");
return;
}
//Nullpointer thrown here (because no Id is submitted)
int requestedId = Integer.parseInt(request.getParameter("id"));
}
private boolean isAJAXRequest(HttpServletRequest request) {
boolean check = false;
String facesRequest = request.getHeader("Faces-Request");
if (facesRequest != null && facesRequest.equals("partial/ajax")) {
check = true;
}
return check;
}
}
Am I doing something wrong?

You are doing it right way. You can also do it using JSF API by checking if PartialViewContext exists and it is an Ajax Request
if(FacesContext.getCurrentInstance().getPartialViewContext() !=null &&
FacesContext.getCurrentInstance().getPartialViewContext().isAjaxRequest()) {
}

Related

Spring Security exclude URL in timeout

In Spring Security, how to exclude one particular URL from resetting the session timeout? Overall application session timeout(server.servlet.session.timeout) is 15 minutes. We have a ajax call from the web page that will get called every 1 minute. This call needs to be secured, but should not impact the session time.
We have tried adding a filter extending ConcurrentSessionFilter. Also, a filter extending SessionManagementFilter. Adding ignoring() skips authentication too. Nothing helped. Can this requirement be achieved in Spring Security? Any suggestions?
This is how i handled it. Just sharing, it may be of help to someone. Please share any better ways.
Spring Security filter is added as last in the chain.
http.addFilterAfter(new SessionInvalidationFilter(timeOutInMinutes), SwitchUserFilter.class);
It keeps track of a lastUpdatedTime, which gets updated for all calls except for those URLs that needs to be ignored. In case, the differential time is greater than the configured timeout, session gets invalidated.
public class SessionInvalidationFilter extends GenericFilterBean {
private static final String LASTUPDATEDDATETIME = "LASTUPDATEDDATETIME";
private static final List<String> ignoredURLs = Arrays.asList("/Notifications/number"); // this is the AJAX URL
private int timeOutInMinutes = 15;
public SessionInvalidationFilter(int timeOutInMinutes) {
this.timeOutInMinutes = timeOutInMinutes;
}
#Override
/**
* LASTUPDATEDDATETIME is updated for all calls except the ignoredURLs.
* Session invalidation happens only during the ignoredURLs calls.
*/
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
try {
if (session != null && request.getRequestURI() != null) {
if (ignoredURLs.contains(request.getRequestURI())) {
Object lastUpdatedDateTimeObject = session.getAttribute(LASTUPDATEDDATETIME);
if (lastUpdatedDateTimeObject != null) {
LocalDateTime lastUpdatedDateTime = (LocalDateTime) lastUpdatedDateTimeObject;
long timeInMinutes = ChronoUnit.MINUTES.between(lastUpdatedDateTime, LocalDateTime.now());
if (timeInMinutes >= timeOutInMinutes) {
log.info("Timing out sessionID:{}", session.getId());
session.invalidate();
SecurityContextHolder.clearContext();
}
}
} else {
session.setAttribute(LASTUPDATEDDATETIME, LocalDateTime.now());
}
}
} catch (Exception e) {
log.error("Exception in SessionInvalidationFilter", e);
}
chain.doFilter(request, response);
}
}

HttpServletRequest getting new session

I have an application that does authentication via oauth.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpResp = (HttpServletResponse) response;
// Check if already logged in
if (getUser(httpReq) != null) {
chain.doFilter(request, response);
return;
}
// Try to parse auth response
if (procAuthResponse(httpReq)) {
chain.doFilter(request, response);
return;
}
// Go to auth server
sendAuthRequest(httpReq, httpResp);
}
This works fine.
In the method procAuthResponse I am paring the response from the server and to this.
HttpSession session = request.getSession();
session.setAttribute(USER_PRINCIPLE_ATR, userInfo);
It works also well, but there is a session scoped class with the method getCurrent user, that is used by servlets.
public UserInfo getCurrentUser() {
HttpSession session = getHttpSession();
if (session == null) {
LOG.warn("Method getCurrentUser: unable to find a session");
return null;
}
Object user = session.getAttribute(OAuthLoginFilter.USER_PRINCIPLE_ATR);
if (!(user instanceof UserInfo)) {
LOG.warn(String.format("Method getCurrentUser, wrong type for attribute %s", OAuthLoginFilter.USER_PRINCIPLE_ATR));
return null;
}
currentUser = (UserInfo) user;
return currentUser;
}
This method gets called multiple times and it turnes out that on the first call everything works as expected and after that the getHttpSession() returns a different session that does not contain any information that is set in the filter class. It is not a new session every time, the session without the needed information is always the same.
Code of getHttpSession()
private HttpSession getHttpSession() {
Object request = FacesContext.getCurrentInstance().getExternalContext().getRequest();
if (!(request instanceof HttpServletRequest)) {
LOG.warn("not a valid http request");
return null;
}
HttpServletRequest hreq = (HttpServletRequest) request;
return hreq.getSession(false);
}
Do you have any idea why this happens?
Thx for your help
There was still an old filter class, not configured in the web.xml, but annotated with #WebFilter("/*").
I deleted this file and now everything works as expected.

Spring interceptor intercepting late

Spring boot 2.1.7 running a test server -- need to check my cache for a hit using the url as key, and then act based on a cache hit or not.
I send a request from my browser for https://localhost:8443/test/param=value --- my filter picks it up, and using code from another answer on SO, the filter constructs the url -- the filter code sees the url is https://localhost:8443/test?param=value
Great!
Then my interceptor gets hit (thanks to Theo on SO), but it thinks the url is https://localhost:8443/favicon.ico -- what's up with that? Not much of an interceptor if I didn't get to intercept the original /test url.
To get around that, in the filter, I stored the "real" url in the ServletContext, and that variable is read out correctly in the interceptor. Seems like an awful hack, and silly that I have to do it. For now I've hard-coded the decision to redirect to url /test2, but back in Chrome, I see the output from test1, not test2.
The network tab in Chrome seems to suggest:
that I was redirected to test2, but only after a request for favicon got inserted (for whatever mysterious reason) and yet as the image shows, the output is clearly test1, not test2.
Something I don't understand is that devtools also shows a response from test2:
#WebFilter( urlPatterns = "/test", description = "a filter for test servlet", initParams = {
#WebInitParam( name = "msg", value = "==> " ) }, filterName = "test filter" )
public class TestFilter implements Filter
{
private FilterConfig filterConfig;
#Override
public void doFilter( ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain )
throws IOException, ServletException
{
String url = getCurrentUrlFromRequest( servletRequest );
// in the debugger, url is correctly shown as
// https://localhost:8443/test/param=value
if ( null != url )
{
ServletContext s = servletRequest.getServletContext();
s.setAttribute( "realUrl", url );
}
servletResponse.getOutputStream().print( filterConfig.getInitParameter( "msg" ) );
filterChain.doFilter( servletRequest, servletResponse );
public String getCurrentUrlFromRequest( ServletRequest request )
{
if ( !( request instanceof HttpServletRequest ) ) return null;
return getCurrentUrlFromRequest( (HttpServletRequest) request );
}
public String getCurrentUrlFromRequest( HttpServletRequest request )
{
StringBuffer requestURL = request.getRequestURL();
String queryString = request.getQueryString();
if ( queryString == null ) return requestURL.toString();
return requestURL.append( '?' ).append( queryString ).toString();
}
#Override
public void destroy()
{
}
#Override
public void init( FilterConfig filterConfig ) throws ServletException
{
this.filterConfig = filterConfig;
}
}
//then the interceptor:
#Component
public class CheckForCacheInterceptor implements HandlerInterceptor
{
#Bean
public MappedInterceptor myInterceptor()
{
CheckForCacheInterceptor ci = new CheckForCacheInterceptor();
ci.setRedirectMapping( "/test2" );
return new MappedInterceptor( null, ci );
}
private String redirectMapping;
#Override
public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler )
{
String url = (String) request.getServletContext().getAttribute( "realUrl" );
// "realUrl" has https://localhost:8443/test/param=value, but I'd like
// to get rid of hack. Problem is that right here, running the same
// exact code (copy/paste of filter's
// getCurrentUrlFromRequest( HttpServletRequest request ) method )
//which gets the correct url in the filter yields
// https://localhost:8443/favicon.ico -- where did that come from?
// TODO check cache using requestUrl as key
boolean foundInCache = false;
if ( foundInCache )
{
// TODO: somehow write cache value to response
// then send response
return false;
} else
{
try
{
// TODO: make direct request,
// get response body, then
response.sendRedirect( redirectMapping );
return false;
} catch ( IOException e )
{
e.printStackTrace();
}
}
return false;
}
So before my questions pile up to the ceiling, I'll ask for help -- how is this favicon request sneaking in before my interceptor even has a crack at the original url, why can't I get the original url in my interceptor, and given that the Chrome devtools shows I am getting through to test2, how is the output coming from the test1 servlet instead of the test2 servlet?
FWIW, I'm getting the exact same behavior in Postman. Thanks so much for any help!
I read another answer on SO (sorry I don't have the link) which has fixed the issue of not intercepting the initial get request to /test -- it said that interceptors only intercept requests going to Controllers, so I needed to have a Controller which was mapped to /test. After writing a quickie Controller, the interceptor is now intercepting as one might expect.

servlet Filter is not allowing to load application resources

I am trying to prevent CSRF(Cross site request forgery). To prevent CSRF I have created filter which will filter every request.
After implementing the javax.servlet.Filter as expected filter does its job. But after implementing servlet filter my application resources are not loading properly.
CSS, jQuery, datatable, all the resources are not loading properly, some time they are loading, some time not.
Before implementing the filter it was working fine.
Sample error in firebug:
"NetworkError: 500 Internal Server Error - http://localhost:8080/myApp/resources/images/bg-report-content.jpg"
"NetworkError: 500 Internal Server Error - http://localhost:8080/myApp/resources/images/bg-header.jpg"
tworkError: 500 Internal Server Error - http://localhost:8080/myApp/resources/css/dataTables.bootstrap.css"
"NetworkError: 500 Internal Server Error - http://localhost:8080/myApp/resources/js/fnStandingRedraw.js"
"NetworkError: 500 Internal Server Error - http://localhost:8080/myApp/resources/js/dataTables.tableTools.js"
This How I implemented the Filter for CSRF
What I am doing is , I have created a class called LoadSalt whic creates the salt(random number). that random number I am taking in jsp. and along with the jsp I am sending it with the request.
LoadSalt calss
public class LoadSalt implements Filter{
public Cache<String, Boolean> csrfPreventionSaltCache= null;
HttpServletRequest httpReq=null;
//int count=0;
#SuppressWarnings("unchecked")
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//count++;
// Assume its HTTP
httpReq = (HttpServletRequest)request;
if(httpReq.getAttribute("csrfPreventionSaltCache")!=null)
{
csrfPreventionSaltCache= (Cache<String, Boolean>) httpReq.getAttribute("csrfPreventionSaltCache");
}
if(csrfPreventionSaltCache == null)
{
// creating a new cache
csrfPreventionSaltCache = CacheBuilder.newBuilder().maximumSize(5000)
.expireAfterAccess(5, TimeUnit.MINUTES).build();
// Setting to httpReq
httpReq.setAttribute("csrfPreventionSaltCache", csrfPreventionSaltCache);
}
// Generate the salt and store it in the users cache
String salt = RandomStringUtils.random(20, 0, 0, true, true, null, new SecureRandom());
//System.out.println("Salt: "+salt);
csrfPreventionSaltCache.put(salt, Boolean.TRUE);
// Add the salt to the current request so it can be used
// by the page rendered in this request
httpReq.setAttribute("csrfPreventionSalt", salt);
chain.doFilter(httpReq, response);
}
public void init(FilterConfig arg0) throws ServletException {
}
public void destroy() {
}
}
The another filter which validate the salt
public class ValidateSalt implements Filter {
public Cache<String, Boolean> csrfPreventionSaltCache= null;
#SuppressWarnings("unchecked")
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// Assume its HTTP
HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpResponse =(HttpServletResponse) response;
String salt =(String) httpReq.getAttribute("csrfPreventionSalt");
// Validate that the salt is in the cache
if(httpReq.getAttribute("csrfPreventionSaltCache")!=null)
{
csrfPreventionSaltCache = (Cache<String, Boolean>) httpReq.getAttribute("csrfPreventionSaltCache");
}
if(csrfPreventionSaltCache !=null && salt !=null && csrfPreventionSaltCache.getIfPresent(salt)!=null)
{
String metodName =httpReq.getMethod();
String saltFromJspPage = httpReq.getParameter("salt");
//String saltFromRequest =(String) httpReq.getAttribute("csrfPreventionSalt");
if(metodName.equalsIgnoreCase("POST"))
{
if(saltFromJspPage!=null && csrfPreventionSaltCache.getIfPresent(saltFromJspPage)!=null)
{
chain.doFilter(httpReq, response);
else
{
//throw new ServletException("Potential CSRF detected!! Please contact to system admin ASAP.");
httpResponse.sendRedirect("/myApp/pages/pageNotFound.jsp");
}
}
else
{
chain.doFilter(httpReq, response);
}
}
else
{
// Otherwise we throw an exception aborting the request flow
//throw new ServletException("Potential CSRF detected!! Inform a scary sysadmin ASAP.");
httpResponse.sendRedirect("/myApp/pages/pageNotFound.jsp");
}
}
public void init(FilterConfig arg0) throws ServletException {
}
public void destroy() {
}
}
servlet filter mapping in web.xml
<filter>
<filter-name>loadSalt</filter-name>
<filter-class>com.mpApp.security.LoadSalt</filter-class>
</filter>
<filter-mapping>
<filter-name>loadSalt</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>validateSalt</filter-name>
<filter-class>com.mpApp.security.ValidateSalt</filter-class>
</filter>
<filter-mapping>
<filter-name>validateSalt</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
What is wrong with my application?
Why servlet filter is not allowing to load resources?, though some time it does work , some time it does not,
What is the route cause of this?
Am I implementing servlet filter in wrong way.
please help.
The url pattern is too wide, will try to apply the salt to every request. Keep it to the dynamic parts you can set and check the salt value, like /transferOperationServlet or /prettyImportantServlet or *.jsp

How to set, get and validate sessions in JSF like PHP $_SESSION[''] [duplicate]

I would like to block the access of some page even if the user knows the url of some pages.
For example, /localhost:8080/user/home.xhtml (need to do the login first) if not logged then redirect to /index.xhtml.
How do that in JSF ? I read in the Google that's needed a filter, but I don't know how to do that.
You need to implement the javax.servlet.Filter class, do the desired job in doFilter() method and map it on an URL pattern covering the restricted pages, /user/* maybe? Inside the doFilter() you should check the presence of the logged-in user in the session somehow. Further you also need to take JSF ajax and resource requests into account. JSF ajax requests require a special XML response to let JavaScript perform a redirect. JSF resource requests need to be skipped otherwise your login page won't have any CSS/JS/images anymore.
Assuming that you've a /login.xhtml page which stores the logged-in user in a JSF managed bean via externalContext.getSessionMap().put("user", user), then you could get it via session.getAttribute("user") the usual way like below:
#WebFilter("/user/*")
public class AuthorizationFilter implements Filter {
private static final String AJAX_REDIRECT_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<partial-response><redirect url=\"%s\"></redirect></partial-response>";
#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 loginURL = request.getContextPath() + "/login.xhtml";
boolean loggedIn = (session != null) && (session.getAttribute("user") != null);
boolean loginRequest = request.getRequestURI().equals(loginURL);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER + "/");
boolean ajaxRequest = "partial/ajax".equals(request.getHeader("Faces-Request"));
if (loggedIn || loginRequest || resourceRequest) {
if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackoverflow.com/q/4194207/157882
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(request, response); // So, just continue request.
}
else if (ajaxRequest) {
response.setContentType("text/xml");
response.setCharacterEncoding("UTF-8");
response.getWriter().printf(AJAX_REDIRECT_XML, loginURL); // So, return special XML response instructing JSF ajax to send a redirect.
}
else {
response.sendRedirect(loginURL); // So, just perform standard synchronous redirect.
}
}
// You need to override init() and destroy() as well, but they can be kept empty.
}
Additionally, the filter also disabled browser cache on secured page, so the browser back button won't show up them anymore.
In case you happen to use JSF utility library OmniFaces, above code could be reduced as below:
#WebFilter("/user/*")
public class AuthorizationFilter extends HttpFilter {
#Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, HttpSession session, FilterChain chain) throws ServletException, IOException {
String loginURL = request.getContextPath() + "/login.xhtml";
boolean loggedIn = (session != null) && (session.getAttribute("user") != null);
boolean loginRequest = request.getRequestURI().equals(loginURL);
boolean resourceRequest = Servlets.isFacesResourceRequest(request);
if (loggedIn || loginRequest || resourceRequest) {
if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackoverflow.com/q/4194207/157882
Servlets.setNoCacheHeaders(response);
}
chain.doFilter(request, response); // So, just continue request.
}
else {
Servlets.facesRedirect(request, response, loginURL);
}
}
}
See also:
Our Servlet Filters wiki page
How to handle authentication/authorization with users in a database?
Using JSF 2.0 / Facelets, is there a way to attach a global listener to all AJAX calls?
Avoid back button on JSF web application
JSF: How control access and rights in JSF?
While it's of course legitimate to use a simple Servlet filter, there are alternatives like
Spring Security
Java EE Security
Apache Shiro

Resources