Send parameter via action bean method - jsf

I read this but my method is a logout where I need to invalidate session so I cannot set bean property.
I just want to pass user language.
public String logout() {
Locale locale = userProfile.getLocale();
// invalidate http session
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "logout";
//I need something like
//return "logout?locale="+locale.getLanguage();
}
EDIT: solved returning this:
return "/logout.xhtml?faces-redirect=true&include-view-params=true&locale=" + locale.getLanguage();

Related

Keep the current locale after invalidating a session with JSF

This method invalidates the session and gets the user back to the home page.
public String restart() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "/index?faces-redirect=true";
}
As a consequence, the locale chosen by the user is forgotten and the app switches back to the default locale of the browser. I want that the locale remains the same even after the session invalidation. The method now looks like:
public String restart() {
Locale currLocale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
FacesContext.getCurrentInstance().getViewRoot().setLocale(currLocale);
return "/index?faces-redirect=true";
}
But the locale still switches back to the browser's default. How can I achieve my goal?

Liferay - autologin hook/portlet doesn't logout the current user

It seems Liferay's autologin hook doesn't logout the current user. So I tried to do it programmatically with the following method call:
request.getSession().invalidate();
but with no success.Does anyone had the same issues with the auto-login hook ?
Hi to logout you have to invalidate the cookies and then invalidate the session see the Liferay LogoutAction for more detail
https://github.com/liferay/liferay-portal/blob/6.2.x/portal-impl/src/com/liferay/portal/action/LogoutAction.java
The main problem is that if a user is logged in, an autologin filter is not executed, so you can't do any logout action in it.
For my solution I created a servlet filter which check some paramteres for autologin and execute logout process. For creating a filter I follow this guide: http://www.liferaysavvy.com/2016/02/liferay-servlet-filter-hooks.html
My code for logout in doFilter method (in servlet filter):
final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
final HttpSession session = request.getSession(false);
if (session != null)
{
session.invalidate();
}
filterChain.doFilter(request, response);
In Liferay 7.2, create a module portlet and do the following:
At the top after import add:
#Component(immediate = true, property = {"key=login.events.pre"}, service = LifecycleAction.class)
Customize your class as below:
public class LoginPreAction implements LifecycleAction
Add:
lifecycleEvent.getRequest().getSession().invalidate();
this will invalidate your session
Now send redirect:
try {
lifecycleEvent.getResponse().sendRedirect("/c/portal/logout");
} catch (IOException e) {
System.out.println("IOException while redirecting:::: "+e.getStackTrace());
}

Bean doesn't dispatch to another page

I've a problem with a bean that doesn't dispatch the response to another page.
This is the code:
#ManagedBean(name = "ssoServiceBean")
public class SSOServiceBean {
#ManagedProperty(value="#{param.samlRequest}")
private String samlRequest;
#ManagedProperty(value="#{param.relayState}")
private String relayState;
#PostConstruct
public void submit() {
System.out.println("1) PostConstruct method called");
//samlRequest = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("samlRequest");
//relayState = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("relayState");
processResponse();
}
//getters and setters omitted for succinctness
private void processResponse(){
System.out.println("2) Processing response");
String uri;
if(samlRequest != null && !samlRequest.equals("") && relayState != null && !relayState.equals("")) {
System.out.println("SAMLRequest: "+samlRequest);
System.out.println("RelayState: "+relayState);
uri = "challenge.xhtml";
System.out.println("3) Sending challenge...");
} else {
uri = "dashboard.xhtml";
System.out.println("3) Sending dashboard...");
}
try {
FacesContext.getCurrentInstance().getExternalContext().dispatch(uri);
System.out.println("4) Done.");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The problem is that the dispatch() method doesn't work properly, and seems to be ignored.
Infact the system responses with an error of the related bean's page ssoservice.xhtml
I've used the Postconstruct annotation because with this bean I've to intercept POST parameters that come from a third-party page.
Once I've received the post parameters, I've to render the challenge.xhtml page, WITHOUT using a redirect directive.
Nextly, the user will submit challenge.xhtml to the related bean ChallengeBean.java .
So, what is the problem? Why dispatch doesn't work?

How to destroy a session after data is presented in a jsf page

I have this problem: I´m making this wonderfull tutorial The NetBeans E-commerce Tutorial . But instead of make it in JSP as is presented, i´m making a JSF version. Just to undertands the logic in construction an application like that.
In certain part the ControllerServlet.java, has this code:
int orderId = orderManager.placeOrder(name, email, phone, address, cityRegion, ccNumber, cart);
// if order processed successfully send user to confirmation page
if (orderId != 0) {
// dissociate shopping cart from session
cart = null;
// end session
session.invalidate();
// get order details
Map orderMap = orderManager.getOrderDetails(orderId);
// place order details in request scope
request.setAttribute("customer", orderMap.get("customer"));
request.setAttribute("products", orderMap.get("products"));
request.setAttribute("orderRecord", orderMap.get("orderRecord"));
request.setAttribute("orderedProducts", orderMap.get("orderedProducts"));
userPath = "/confirmation";
// otherwise, send back to checkout page and display error
As you can see, the author invalidates the session, in order to permit another purchase order. I made an Managed Bean with session scope in order to mantain the data avalaible throught the whole session. But when I try to clean up the session, as in the tutorial the author does, I can´t receive the data for confirmation.
Then, I made a different managed bean in order to have one to process the order (CartManagerBean), and another one to present the confirmation (ConfirmationMBean). I just injected the confirmatioBean into the cartBean to pass the orderId, necessary to present the data. In the confirmationBean, I made a cleanUp() method that invalidates the session.
But always, the data is not presented. So if any one can tell me what to do, I´ll appreciate.
Here is the part of my cartBean's code that pass the data to the confirmation bean:
...
#ManagedProperty(value ="#{confirmationBean}")
private ConfirmationMBean confirmationBean;
...
public String makeConfirmation() {
FacesContext fc = FacesContext.getCurrentInstance();
if (!cartMap.isEmpty()) {
int orderId = orderManager.placeOrder(name, email, phone, address, credicard, cartMap);
// if order processed successfully send user to confirmation page
if (orderId != 0) {
// get order details
confirmationBean.setOrderId(orderId);
// dissociate shopping cart from session
cartMap.clear();
// end session
//fc.getExternalContext().invalidateSession();
}
}
return "confirmation";
}
As you can see, I commented the part that invalidates the session. Here is the code that I implemented for the ConfirmationMBean:
#ManagedBean(name = "confirmationBean")
#SessionScoped
public class ConfirmationMBean implements Serializable{
private Customer customer;
private List<OrderedProduct> orderedProducts;
private CustomerOrder orderRecord;
private List<Product> products;
private int orderId;
#EJB
private OrderManager orderManager;
public void cleanUp(){
FacesContext fc = FacesContext.getCurrentInstance();
fc.getExternalContext().invalidateSession();
}
private void init(){
Map<String, Object> orderMap = orderManager.getOrderDetails(orderId);
customer = (Customer) orderMap.get("customer");
orderRecord = (CustomerOrder) orderMap.get("orderRecord");
orderedProducts = (List<OrderedProduct>) orderMap.get("orderedProducts");
products = (List<Product>) orderMap.get("products");
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public List<OrderedProduct> getOrderedProducts() {
return orderedProducts;
}
public void setOrderedProducts(List<OrderedProduct> orderedProducts) {
this.orderedProducts = orderedProducts;
}
public CustomerOrder getOrderRecord() {
return orderRecord;
}
public void setOrderRecord(CustomerOrder orderRecord) {
this.orderRecord = orderRecord;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
init();
cleanUp();
}
}
As you can see, when the orderId is setted by the preceding bean, the data is requested from the database, and populates the variables to present in the facelet. ¿Where or how I have to use the cleanUp method in order to obtain the same result that the tutorial?
Thanks in advance.
Put the bean where you're invoking the action in the request scope instead of session scope and get hold of the desired session scoped bean as a (managed) property.
#ManagedBean
#RequestScoped
public class SubmitConfirmationBean {
#ManagedProperty("#{cartBean}")
private CartBean cartBean;
// ...
}
And reference it by #{submitConfirmationBean.cartBean...} instead of #{cartBean...}.
Alternatively, explicitly put the desired session scoped bean in the request scope in the same action method as where you're invalidating the session:
externalContext.getRequestMap().put("cartBean", cartBean);
This way the #{cartBean...} will refer the request scoped one instead of the session scoped one which is newly recreated at that point because you destroyed the session. The request scoped one is lost by next request anyway.

Programmatically control login with Servlet 3.0

I've tested the default security containers in Glassfish 3.0.1 and come to the conclusion that I won't spend any more time on that. Instead I want to control the verification myself. But I need some guidance to get me on right track.
At the moment I have a UserBean that has a login/logout function (see below). And I don't want to use the *j_security_check* built in container, but use core JSF 2.0.
My questions are;
Do I need a ServletFilter to redirect traffic if the user is not logged in (if accessing certain folders)?
How do I store User Pricipals after the user successfully logged in ?
Appreciate any help or link to a example, greetings Chris.
PS. Excuse me for clustering two questions together
#ManagedBean
#SessionScoped
public class UserBean {
private AuthenticateUser authenticateUser;
...
public String login() {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
JsfUtil.log("Username : " +authenticateUser.getUserName());
JsfUtil.log("Password : " +authenticateUser.getPassword());
AuthenticateUser authRequest = authenticationFacade.find(authenticateUser);
try {
if(!authRequest.equals(authenticateUser))
return "/loginError";
request.login(authenticateUser.getUserName(), authenticateUser.getPassword());
return "";
} catch(ServletException e){
JsfUtil.addErrorMessage(e, "Incorrect username or password, please try again.");
return "/loginError";
}
...
public String logOut() {
String result = "/index?faces-redirect=true";
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try {
request.logout();
} catch (ServletException e) {
JsfUtil.log("Failed to logout user!" +e.getRootCause().toString());
result = "/loginError?faces-redirect=true";
}
return result;
}
When you want to utilize request.login(), then you should really have configured a Realm in the container which represents the user database. But you seem to have replaced the Realm by some AuthenticationFacade. In this case, the request.login() is not useful for you.
You need to just put the user in the session scope and intercept on that. Here's a kickoff example:
#ManagedBean
#SessionScoped
public class UserManager {
#EJB
private UserService userService;
private String username;
private String password;
private User current;
public String login() {
current = userService.find(username, password);
if (current == null) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Unknown login, try again"));
return null;
} else {
return "userhome?faces-redirect=true";
}
}
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "index?faces-redirect=true";
}
public boolean isLoggedIn() {
return current != null;
}
// Getters/setters (but do NOT provide a setter for current!)
}
When taking authentication in hands like this, then you definitely need a filter to restrict access. When using container managed security you would typically specify it as <url-pattern> of <security-constraint> for this. But without it, you've to take it in your hands. It's good to know that JSF managed beans are keyed by their managed bean name in any scope.
UserManager userManager = ((HttpServletRequest) request).getSession().getAttribute("userManager");
if (userManager == null || !userManager.isLoggedIn()) {
((HttpServletResponse) response).sendRedirect("login.xhtml");
} else {
chain.doFilter(request, response);
}
Map the above filter on the desired URL-pattern.
When you still want to reconsider using container managed authentication, then the following related answers may be useful:
Java EE Login Page Problem (and Configuring Realm in Glassfish)
Performing user authentication in Java EE / JSF using j_security_check
Be aware if you are if you are using JDBC realm security. There are some fixed/expected words in the fields where you configure the realm in the Glassfish admin console.
In the JAAS Context: filed, you have to type: jdbcRealm. This keyword makes the security container use the expected JDBC realm. If you type something else, it won't work.
Here is good example, done by Gordan Jugo; Netbeans/Glassfish JDBC Security Realm

Resources