I am developing a JSF web based application that makes use of CDI managed beans and Shiro managed sessions. The problem I've got is when a JSF page that references an object annotated with #javax.enterprise.context.SessionScoped an UnknownSessionException is thrown. I have set the logging level to finest and looking through the application server log file I can see that when the user accesses the login page a new session is created along with a cookie that sets JSESSIONID to b2b69494-2236-467f-9e0b-3c262c74b7c4. When the user accesses the page that references the SessionScoped bean the cookie is updated to have a JSESSIONID set to 49253beaee601d4107cba4b61c77, at this point an UnknownSessionException is thrown. When accessing pages that reference a managed bean annotated with either #javax.enterprise.context.ApplicationScoped or #javax.faces.view.ViewScoped everything works fine.
It appears that when accessing a page that references a session scoped bean, the servlet container is creating a new session rather than allowing the Shiro managed session to be used. If I configure Shiro to use something other than JSESSIONID then the error isn't thrown but instead two sessions appear to be created, one managed by Shiro and the other managed by the servlet container.
The contents of my shiro.ini file is
[main]
authc.loginUrl = /login.xhtml
authc.usernameParam = login:username
authc.passwordParam = login:password
authc.rememberMeParam = login:rememberMe
user.loginUrl = /login.xhtml
authc.successUrl = /app/index.xhtml
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionManager = $sessionManager
[users]
admin = password
[urls]
/login.xhtml = authc
/app/** = user
My environment is using Glassfish 4.1, Java EE version 7, Mojarra version 2.2.7 for JSF, Weld version 2.2.2 for CDI, and Shiro version 1.2.3. I have also reproduced the same issue on Glassfish version 4.0 albeit with earlier versions of Mojarra and Weld.
I have uploaded the relevant portion of the application server log to PasteBin which can be accessed with the URL http://pastebin.com/2sPHfdTQ
I've also created an example Maven project to demonstrate the problem. The example project can be downloaded from https://www.dropbox.com/s/1x9pe2o9ja0q9jw/TestJavaEE-web.zip?dl=0 which contains the source code and the complied war file.
Is anyone else currently using CDI managed session scoped beans with Shiro managed sessions, and if so have you had any problems?
Is there a configuration setting I've missed either in Shiro or GlassFish or is this a bug?
Note: I have previously posted this question on the Shiro mailing list but I'm yet to find a solution and I'm hoping that there will be a wider audience on StackOverflow.
Related
I was wondering where is located the code that automatically create a temporary file when you send a multipart request using StandardServletMultipartResolver?
Can i disable that behavior? I want to decide how its going to be stored and where. I don't want spring to do it for me.
I'm considering creating my own resolver but I cant find information on how to disable spring default behavior.
To quote from API docs StandardServletMultipartResolver does not support temporary file configuration on resolver level rather it is to be done on servlet registration level -
In order to use Servlet 3.0 based multipart parsing, you need to mark the affected servlet with a "multipart-config" section in web.xml, or with a MultipartConfigElement in programmatic servlet registration, or (in case of a custom servlet class) possibly with a MultipartConfig annotation on your servlet class.
Configuration settings such as maximum sizes or storage locations need to be applied at that servlet registration level; Servlet 3.0 does not allow for them to be set at the MultipartResolver level.
So either you can configure it on servlet or switch to CommonsMultipartResolver which has the support to set the temp directory out-of-the-box as it inherits it from CommonsFileUploadSupport.setUploadTempDir (see respective docs here and here)
I am trying to implement a function where a admin user can terminate another user's session. I followed the official Spring Security documentation here: http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#list-authenticated-principals and started with getting all currently logged in users through sessionRegistry.getAllPrincipals(), but it always returned an empty list.
I set a breakpoint in SessionRegistryImpl.registerNewSession() and could see it did indeed get invoked and it did add the UserDetails (my own implementation with both equals() and hashCode() implemented) to the hashmap principals. But when I access sessionRegistry bean from a Spring MVC controller, the list is always empty.
My configuration looks pretty much the same as the documentation.
How to fix this? Did anyone successfully get SessionRegistry to work with Spring Security 4? I remember I made it work with Spring Security 3 by following these intructions(enter link description here)
OK, so I fixed the issue by cleaning up the Spring configuration files, as suggested by the comments. Someone messed up with the web.xml - he added a reference to the context XML that is already referenced by the Spring's DispatcherServlet, causing it to be loaded twice. He didn't know it, because Spring references the file implicitly.
P.S.
I learned my lessons, but 2 things the Spring folks could do better (maybe in Spring 5?):
There shouldn't be implicit context file loading. Currently, the framework will try to load the application context from a file named [servlet-name]-servlet.xml located in the application's WebContent/WEB-INF directory. Convention over configuration fails in this case.
There should be warning when a bean is loaded twice, if someone need to override a bean definition, he must declare explicitly. Otherwise it would take a lot of time to debug the kind of error this mistake will cause.
Im facing problem expiring session in JSF 2.2, I tried many solutions but in vain.
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
and
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
request.getSession().invalidate();
I checked bean with both scopes 'View' and 'Session'. Im not using JSF scope annotations rather our application architecture restrict us to use Spring scope like #scope("session") and i created view scope bean (according to: http://comdynamics.net/blog/109/spring3-jsf2-view-scope/) and register with Spring scopes and used like #scope("view"). It doesn't throw any exception, calls bean logout code and navigate to login page but after logging out when i try to access homepage or any other page it shows all session data even in different browser.
It was working fine with JSF 1.2, I upgraded JSF from 1.2 to 2.2 and now its not working since.
Please help me in this regard.
I want to know about setting and un-setting the session in JSF2.0. Although following some blogs and books (Core JavaServer Faces-3rd Edition), i got to know that using annotation #SessionScoped we can set any manage bean to be in session. I have a loginBean which is #ManagedBean and SessionScoped declared. On the top right corner, my web has login button.
When this session is created (i am not setting it manually, that is why i am confused) and when i gets destroyed? It must be destroyed either by time out or by clicking in logout button only.
JSF uses the Servlet API under the covers. A session scoped managed bean is in essence set as an attribute of the HttpSession. It will be created and set whenever the EL expression referencing the managed bean #{sessionBean} is evaluated for the first time. It will be "removed" from the session whenever the session expires (by either a restart of the client or a timeout in the server) or get invalidated. If you let your logout button call ExternalContext#invalidateSession(), then the session will be invalidated.
If you're familiar with the basic Servlet API, you should already understand how this all works. For an in-depth explanation of the Servlet's HttpSession works under JSF's covers, read this answer: How do servlets work? Instantiation, sessions, shared variables and multithreading.
In jsf 2.0 we can set total class ob as session like i mention
Class_name sm;
ExternalContext extContext = FacesContext.getCurrentInstance().getExternalContext(); extContext.getSessionMap().put("Give name for access this property",sm);
Class_name sm = (Class_name) extContext.getSessionMap().get("Give name for access this property");
I am trying to override the tomcat session manager with an embedded tomcat.
These are the steps preformed in-order to load the context.xml that defines the manager entity.
..
Context context = tomcat.addWebapp(contextPath, appBase);
File configFile = new File ("D:\\context.xml");
context.setConfigFile(configFile.toURI().toURL());
tomcat.start();
..
The session manager seems to be recognized as it's constructor is being invoked but the startInternal() method is never invoked and the session manager being used is the old tomcat session manager.
The weird thing is that when defining the same configuration in a non embedded tomcat, the session manager is being overridden without problems.
Would appriciate any help on the subject.
Non embedded tomcat uses server.xml and embedded tomcat does not uses server.xml file rather we need to pass the arguments in the method.