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

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

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);
}
}

Spring Session not working on Tomcat 8 when using Tiles - SESSION Cookie is not set as response is already included

I am using Spring Session 1.2.0.RELEASE on a Spring Boot Project. This is packaged as a war and deployed on Tomcat 8.
I have followed Spring Session documentation and configured it properly. The problem is that the entry point to the application is a controller that sets some value on session but the SESSION cookie is not sent to the browser.
Debugging I see that:
org.springframework.session.web.http.CookieHttpSessionStrategy.onNewSession() tries to write the cookie:
this.cookieSerializer
.writeCookieValue(new CookieValue(request, response, cookieValue));
org.springframework.session.web.http.DefaultCookieSerializer.writeCookieValue() sets the cookie in the response:
response.addCookie(sessionCookie);
The cookie isn't actually written. The underlying response object is org.apache.catalina.core.ApplicationHttpResponse. Its addCookie() method is:
/**
* Disallow <code>addCookie()</code> calls on an included response.
* #param cookie The new cookie
*/
#Override
public void addCookie(Cookie cookie) {
if (!included)
((HttpServletResponse) getResponse()).addCookie(cookie);
}
The problem is that included attribute, which at some point is set true, preventing the cookie from being added.
This happens when the jsp (using tiles) is being serviced:
UPDATE:
This is the moment when the response is being marked as included (when standard.jsp tiles layout is inserting an attribute:
<tiles:insertAttribute name="header" ignore="false"/>
To work around this problem I ended up creating a filter to enforce the creation of the session.
As seen, the first call to the controller didn't add the cookie because during the Tiles-JSP rendering the response was already marked as included. What I do is forcing the creation of the session in the filter and redirecting asking the very same requestURI. This way, since the call doesn't involve a tiles rendering the cookie is created and can be used right away in the next calls.
#Bean
#ConditionalOnExpression("${sessionEnforcerFilter.enabled:true}")
public FilterRegistrationBean sessionEnforcerFilter(){
logger.info("Registering sessionEnforcerFilter");
FilterRegistrationBean frb = new FilterRegistrationBean();
frb.setName("sessionEnforcerFilter");
frb.setFilter(new SessionEnforcerFilter());
frb.setUrlPatterns(Arrays.asList(new String[]{"/*"}));
return frb;
}
public class SessionEnforcerFilter implements Filter{
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
HttpServletResponse httpServletResponse = (HttpServletResponse)response;
if(httpServletRequest.getSession(false)==null){
logger.debug("sessionEnforcerFilter.doFilter () - Session is null - forcing its creation");
httpServletRequest.getSession();
String requestURI = httpServletRequest.getRequestURI();
logger.debug("sessionEnforcerFilter.doFilter () - Repeating request [{}]", requestURI);
httpServletResponse.sendRedirect(requestURI);
}else{
chain.doFilter(httpServletRequest, response);
}
}
#Override
public void destroy() {}
}
summary
Hold breakPoint in SessionRepositoryResponseWrapper.onResponseCommitted().
Check that the response object inside the SessionRepositoryRequestWrapper is a non-wrapped response. (included = false)
If it is a wrapped response object, make sure that the sessionRepositoryFilter comes first.
================
Spring-session is already handling the problem when 'DispatcherType.INCLUDE (included = true)'.
SessionRepositoryResponseWrapper.onResponseCommitted() is trying to addCookie to the original response object.
The sessionRepositoryFilter must be in the first position to wrap the original applicationHttpResponse passed by tomcat.
Problem Situation
The SessionRepositoryRequestWrapper receives the wrapped response and holds it.
When executing doInclude() in the servlet container, find the original reponse and wrap it with ApplicationHttpResponse (included = true).
Then, SetResponse (new wrapping response) to the innermost wrapper.
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat.embed/tomcat-embed-core/8.0.24/org/apache/catalina/core/ApplicationDispatcher.java#ApplicationDispatcher.doInclude%28javax.servlet.ServletRequest%2Cjavax.servlet.ServletResponse%29
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat.embed/tomcat-embed-core/8.0.24/org/apache/catalina/core/ApplicationDispatcher.java#ApplicationDispatcher.wrapResponse%28org.apache.catalina.core.ApplicationDispatcher.State%29
Spring-session does an addCookie on the response (expecting the original response) stored in SessionRepositoryResponseWrapper.onResponseCommitted(), but it can not because it is set to 'included = true'.

How to get request attributes in authentication-success-handler

I am trying to do few things in authentication-success-handler and I need to access few values which was part of initial request data being posted to Spring security.
I am posting following information when user trying to do login
j_username
j_password
storeCode
Spring security is able to authenticate user successfully and is calling "authentication-success-handler".
public class WebshopAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler
{
public WebshopAuthenticationSuccessHandler() {
}
#Override
public void onAuthenticationSuccess(final HttpServletRequest request,
final HttpServletResponse response, final Authentication authentication)
throws IOException, ServletException {
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
request.getAttribute( "storeCode" );
attr.getRequest().getAttribute( "storeCode" );
}
}
But in all way, I am not able to get value of storeCode and its coming as null.
Not sure what I am doing wrong.
I am assuming that Spring is creating a new instance of Request and response while calling onAuthenticationSuccess, but how can I pass/ retrieve values which passed passed from the login page?
If the data is from an HTTP POST request, you should be using getParameter, not getAttribute. Attributes are server-side state only, not submitted by the client.

Struts2 and servlet integration

i am getting data from action class to servlet by adding data to session.whenever i am clicking the item in select list onchange event is fired that function is invoked the our servlet up to now OK,whenever we send second time request that servlet is not called why? and also comparsion is failed it will maintain previous values only.here i am sending request from ajax.pls can any one provide solution ?
AjaX code
function verify_details()
{
var resourceId=document.getElementById("res").value
var url="/EIS10/ResourceTest?resourceId="+resourceId;
ajax(url);
}
Action class Code:
listResource=taskService.getUserList(taskId);
System.out.println("The list Of Resources are::"+listResource);
HttpSession session=request.getSession();
session.setAttribute("listResource", listResource);
ServletCode
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
System.out.println("Servlet is Called...........");
String resourceId=request.getParameter("resourceId");
boolean t=false;
System.out.println("Your Clicked Id::"+resourceId);
HttpSession session=request.getSession();
List l=(List)session.getAttribute("listResource");
System.out.println("Resource List in Servlet:"+l);
if(l!=null)
{
System.out.println("The Size of List::"+l.size());
Iterator itr=l.iterator();
while(itr.hasNext())
{
String s=itr.next().toString();
System.out.println("Elements in List:"+s);
if(s.equals(resourceId))
t=true;
}
response.setContentType("text/html");
if (t) {
response.getWriter().write("Y");
} else {
response.getWriter().write("N");
}
}
}
}
It's probably because the browser returns the contents from its cache at the second request. See http://spacebug.com/solving_browser_caching_problem_of_ajax-html/ for a solution, or use an AJAX library (jQuery for example) which can handle this for you.
Besides, if you're using Struts, why do you use a bare servlet to handle your AJAX call? Why don't you use a Struts action?

Spring Security: How to get the initial target url

I am using the spring security to restricted urls. I am trying to provide signup and login page, on the same page.
On login spring security transfers to the restricted page. However i am trying to pass the target url to the signup process, so that after signup we can redirect to the restricted page.
How to get the actual URL that user was redirected from.
Any Ideas?
This is how i got the URL from the Spring Security.
SavedRequest savedRequest = (SavedRequest)session.getAttribute(
AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY);
String requestUrl = savedRequest.getFullRequestUrl();
They moved things around a bit in spring security 3.0, so the above code snippet doesn't work anymore. This does the trick, though:
protected String getRedirectUrl(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if(session != null) {
SavedRequest savedRequest = (SavedRequest) session.getAttribute(WebAttributes.SAVED_REQUEST);
if(savedRequest != null) {
return savedRequest.getRedirectUrl();
}
}
/* return a sane default in case data isn't there */
return request.getContextPath() + "/";
}
with spring security 4.1.4:
#Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request, response);
if (savedRequest != null) {
response.sendRedirect(savedRequest.getRedirectUrl());
}
else{
response.sendRedirect("some/path");
}
}
DefaultSavedRequest savedRequest = (DefaultSavedRequest)session.getAttribute("SPRING_SECURITY_SAVED_REQUEST");
String requestURL = savedRequest.getRequestURL(); // URL <br>
String requestURI = savedRequest.getRequestURI(); // URI

Resources