Session scoped bean not stored in user session - jsf-2

I tried to develop a simple authentification application based on BaluC's answer in JSF HTTP Session Login, but the problem is that my session scoped bean UserManager is not stored in the user session, so when the LoginFilter checks if the user is logged in,
UserManager userManager=(UserManager)req.getSession().getAttribute("userManager");
it returns null !
Any Idea on how to fix this problem ?

You can try to get it from the context like :
FacesContext context = FacesContext.getCurrentInstance();
UserManager userManager = context.getApplication().evaluateExpressionGet(context, "#{userManager}", UserManager.class);

Related

how to set and retrieve data from the application context?

In my JSF application I need to store some data into the application context so that I can get it back. Is this possible and if yes then how to do this?
The reason I need to do this is: https://stackoverflow.com/questions/20273846/session-scoped-bean-getting-recreated-for-every-request-upon-redirection
Create a application scoped bean and store your data there.
#ManagedBean
#ApplicationScoped
public void Bean {...}
Or access the application context directly by
ApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());

How to clear an object of the session scoped managed bean?

I am developing a login based application in JSF with primefaces. In that I kept the logged user info in session scoped managedbean and I need to clear that details when he logged out, So How to clear those details which are in SessionScoped ManagedBean object?
You need to invalidate the current session by calling the following function in your action method:
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
Also, as the session scoped beans are trashed buring the subsequent request, be sure to send a redirect:
FacesContext.getCurrentInstance().getExternalContext().redirect("/login.xhtml");
Or, simply return a navigation case outcome from your method:
return "login.xhtml?faces-redirect=true";
In case you don't want to invalidate the session and, effectively, retaining your session scoped beans (which is a bad practice in my opinion), just nullify all of the user data (which was hopefully collected in one session scoped managed bean) in the logout method (you may need to inject that bean in case the logout method resides in another session scoped bean).
You don't need to clear session scoped managed bean manually. Just clear the user session.
By using following code in servlet for logout.
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
System_Properties system_Properties=new System_Properties();
PrintWriter out = response.getWriter();
try {
request.getSession().invalidate();
}finally {
out.close();
}
}
If you still manually clear the managed bean data then it can be done by using following code.
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("managed_bean_name", null);
Where "mananged_bean_name" is name of your managed bean.
Hope it helps
When the user logout, the session is destroyed and all the SessionScoped ManagedBean objects too

Spring Security - Invalid property 'principal' of bean class [org.springframework.security.authentication.UsernamePasswordAuthenticationToken]

I had to implement a custom "authentication provider" for a project, but I ran into troubles when trying to acces the Authentication's object properties in JSP. Details:
My custom authentication provider successfully creates an Authentication object
Authentication auth = new UsernamePasswordAuthenticationToken(username, password, getAuthorities(userRoles));
log.info("User is authenticated");
return auth;
(Only relevant code here)
Then, in the controller method, I just display a log message with the username (this proves that the Authentication object is created and placed in the security context):
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
log.info("Welcoming user " + auth.getPrincipal());
Then in the JSP page I want to display the user name using
<sec:authentication property="principal"/>
However, this raises an error 500:
org.springframework.beans.NotReadablePropertyException: Invalid property 'principal' of bean class [org.springframework.security.authentication.UsernamePasswordAuthenticationToken]: Bean property 'principal' is not readable...
I also noticed that
<sec:authorize ifAnyGranted="role">...
is not working, although the user has the necessary roles added in the Authentication object.
Is there something I'm doing wrong? The authentication works fine, I just can't access the authentication object's properties.
Thank you very much and have a good day.
your AuthenticationProvider must return UserDetails object.
From spring documentation
This tag allows access to the current Authentication object stored in the security context. It renders a property of the object directly in the JSP. So, for example, if the principal property of the Authentication is an instance of Spring Security's UserDetails object, then using will render the name of the current user.
Given that I can't see anything wrong with your case, I think it can be SPR-8347 bug, which is fixed in Spring 3.1.1. Can you do an upgrade?
Old question, but I think that I can help other folks.
As the first parameter of UsernamePasswordAuthenticationToken you may send a User.
Instead of passing the username, pass the user itself. But the user must be a class that extends org.springframework.security.core.userdetails.UserDetails:
Authentication auth = new UsernamePasswordAuthenticationToken(user, password, getAuthorities(userRoles));
log.info("User is authenticated");
return auth;
See the method that you was using:
public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
super.setAuthenticated(true); // must use super, as we override
}
Now, in yout tamplete, um can use something like this:
<span class="hidden-sm-down" sec:authentication="principal.email">Email</span>

Spring 3, Spring Security. Extract authenticated User object

This is a Spring Security question.
In my application, I have a User entity as a domain object. This object contains implementation to support Spring UserDetails object. The authentication (login/logout) process works fine.
The challenge is that I need to extract that object from the session to make 'business logic' decisions in my code.
I've been reading about querying SecurityContextHolder, but frankly, I still don't know what is the best approach, given that multiple Spring versions seem to be a factor in those discussions. Also, the Principal object isn't a solution for me, as it does not seem to contain any access level or role information.
Below is a simple controller to illustrate my challenge. It has my User domain object hardcoded. I need to replace that block with code that will obtain the User object from Spring Security session. I'm looking for the best way to do this within Spring 3.
Can I get this object as my domain object or do I need to get it as Spring UserDetails object and manually convert it?
Can this Security context lookup be injected somehow into my controller?
public class HomeController {
#RequestMapping(value="/home.html", method=RequestMethod.GET)
public ModelAndView getHomePage(Map<String, Object> model) {
// Get current user
User currentUser=new User();
currentUser.setUserName("Admin");
currentUser.setAccessLevel(UserAccessLevel.ADMINISTRATOR);
// Construct HomePage bean
HomeBean bean=new HomeBean();
bean.setCurrentUserName(currentUser.getUserName());
// Construct list of catalogs
Collection<String> catalogList=new ArrayList<String>();
catalogList.add("articles");
catalogList.add("files");
catalogList.add("comments");
if(currentUser.hasAdministratorAccessLevel()) {
catalogList.add("users");
}
bean.setCatalogList(catalogList);
// Construct and return ModelAndView
ModelAndView mav=new ModelAndView();
mav.setViewName(WebView.HOME_PAGE.getViewName());
mav.addObject(bean.getBeanId(), bean);
return mav;
}
=== Update 2012-01-07 ======================================================
I'm working with Luke's suggestion. The method that gets UserDetails from session and converts it to a returned my domain User object is in my UserService.
Here's my controller:
#Controller
public class HomeController {
#Autowired
private UserService userService;
#RequestMapping(value="/home.html", method=RequestMethod.GET)
public ModelAndView getHomePage(Map<String, Object> model) {
// Construct HomePage bean
HomeBean bean=new HomeBean();
User currentUser=userService.getCurrentlyAuthenticatedUser();
bean.setCurrentUserName(currentUser.getUserName());
And here's key code from UserServiceImpl.getCurrentlyAuthenticatedUser():
#Override
public User getCurrentlyAuthenticatedUser() {
User currentUser=new User();
Authentication a = SecurityContextHolder.getContext().getAuthentication();
UserDetails currentUserDetails = (UserDetails) a.getPrincipal();
if(currentUserDetails==null) {
return currentUser;
}
currentUser.setUserName(currentUserDetails.getUsername());
This works but am I doing this right? Feedback much appreciated. I am still unable to retrieve my User domain object from the session. I'm retrieving Spring's UserDetails object and with it constructing my domain User object but in the process some information is lost.
Normally, the principal object contained in the successful Authentication will be an instance of your user object. So, for a quick solution, use
Authentication a = SecurityContextHolder.getContext().getAuthentication();
User currentUser = (User)a.getPrincipal();
But also (once you get that working), you might want to look at the answer I just gave (to a similar question) on how to inject a custom security context accessor.
Spring also provides an annotation #AuthenticationPrincipal, it is used to resolve Authentication.getPrincipal(). It can be used like below...
public ResponseEntity<UserProfileResponse>UserProfile(#AuthenticationPrincipal JwtAuthenticationToken principal){

Struts 2 Session in interceptor

I am trying to access session object from within my interceptor by implementing SessionAware interface (I've implemented the setSession method), but I am not able to get my session object this way.
Then I tried ActionContext.getContext().getSession() and I am able to get the session, but I don't know but its coming out to be empty for only the first time in every browser for every user & then it comes filled when another action is invoked.
I assume there is something wrong going with the session. Why is it giving me an empty session only for the first time? Does it set something only after giving empty session for the first time?
If this is the case then everyone will be shown as guest on their first request & then with a username on their 2nd request & hence forth.
Or am I getting the session in the wrong way?
I saw code to get sessions in interceptors, but this does not work for me as it cannot find the constant HTTP_REQUEST.
final ActionContext context = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST);
HttpSession session = request.getSession(true);
Object user = session.getAttribute(Constants.USER_HANDLE);
Any suggestion on resolving any of the problems?
Something I forgot to mention - my website is a secure site(https), so if the user is not logged in, it would not let him enter the website & if he is logged in, at least his username should be there in the session. Shouldn't it be?
I have an interceptor that also grabs the session as a map. Have you tried something like this? This works for me.
public String intercept( ActionInvocation actionInvocation ) throws Exception {
Map session = actionInvocation.getInvocationContext().getSession();
You can use the following to return the HttpSession -- and create it if it doesn't exist.
HttpSession session = ServletActionContext.getRequest().getSession(true);
If you need the Map instead, then you can just call this right after that last call (since you passed true, the session would have been created and the next call will return a blank session map).
Map<String, Object> session = ActionContext.getContext().getSession();
Alternatively, you can use the CreateSessionInterceptor early in your stack so that the session is created by the time you need it. Then just use the map example above to get it.
FYI: ServletActionContext is a subclass of ActionContext that just has convenience methods for getting the request and response without needing to use the constants like you were trying in your example.
Try this. It worked for me in struts 2.0.14.
public String intercept(ActionInvocation ai) throws Exception {
Map session = ActionContext.getContext().getSession();
You can get the session on Interceptor using ActionContext itself...refer the following code snippet:
SessionMap<String, Object> session = ActionContext.getContext().getSession();
or alternatively you can follow this approach:
The request is available on the ActionContext instance, which is made available via ThreadLocal.
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession(true);
Add the import:
import org.apache.struts2.StrutsStatics;

Resources