request.getSession() is null - jsf

I will appreciate if someone help me with the following problem.
I have a jasper report which i fill in a PrintingBean and its all good. The moment I clicked on a print preview button (opening the applet) my app throws a null pointer exception at:
if (bean.getPrintingDataList() != null && !bean.getPrintingDataList().isEmpty())
It seems like it makes new session (but I can't see that on gui, its all good). My manageBean is a SessionScoped. This is my whole method:
private void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
JasperPrint jasperPrint = null;
try {
PrintingBean bean = (PrintingBean) request.getSession().getAttribute("printMB");
if (bean.getPrintingDataList() != null && !bean.getPrintingDataList().isEmpty()) {
jasperPrint = printManager.print(bean.getPrintingDataList());
}
} catch (Exception ex) {
Logger.getLogger(JasperPrintServlet.class.getName()).log(Level.SEVERE, null, ex);
}
if (jasperPrint != null) {
response.setContentType("application/octet-stream");
ServletOutputStream ouputStream = response.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(ouputStream);
oos.writeObject(jasperPrint);
oos.flush();
oos.close();
ouputStream.flush();
ouputStream.close();
}
}

The session is maintained by a cookie with the name JSESSIONID. Normally, this cookie is set by the server on start of session and this cookie is returned back from client to server on every subsequent single HTTP request throughout the session. The client (the webbrowser) does this all transparently. See also How do servlets work? Instantiation, sessions, shared variables and multithreading.
In the applet you need to simulate the same as the webbrowser is doing. When the applet connects to the servlet and needs to access the same session as the page which is serving the applet, then you should make sure that you append the very same session cookie to the HTTP request which is been sent by the applet.
The easiest is to pass the session ID as a parameter to the applet:
<param name="JSESSIONID" value="#{session.id}">
(note: I'm assuming that you're using Facelets as view technology, if you were using JSP, then you should use ${pageContext.session.id} instead)
So that you can set the needed session cookie in the applet accordingly:
String jSessionID = getParameter("JSESSIONID");
URL servletURL = new URL(getCodeBase(), "yourServletURL");
URLConnection connection = servletURL.openConnection();
connection.setRequestProperty("Cookie", "JSESSIONID=" + jSessionID);
// ...
This should give you the same session back in the servlet on request.getSession().

If there is a request than there must be a session. I think .getAttribute("printMB") is null. You must check before cast it to PrintingBean.

Related

How would microfrontend work using Apache Wicket?

I want to achieve microfrontend architecture using Apache Wicket but I cannot make it work.
add(new WebMarkupContainer("testFrame") {
#Override
protected void onComponentTag(ComponentTag tag) {
checkComponentTag(tag, "iframe");
super.onComponentTag(tag);
//Won't work like this if you want to send credentials.
//tag.put("src", "http://localhost:8089/httpBasicAuthenticated/url/page/");
}
#Override
public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
Response response = getRequestCycle().getResponse();
final CredentialsProvider provider = new BasicCredentialsProvider();
String username = "user";
String password = "password";
final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
provider.setCredentials(AuthScope.ANY, credentials);
final HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build();
HttpResponse httpResponse = null;
String body = "";
try {
httpResponse = client.execute(new
HttpGet("http://localhost:8089/httpBasicAuthenticated/url/page/"));
body = IOUtils.toString(httpResponse.getEntity().getContent(), "UTF-8");
} catch (final IOException e) {
e.printStackTrace();
}
response.write(body);
}
});
Result from inspecting the element
I am trying out with an iframe but it's not rendering the page inside the iframe. Is there something wrong? How would I send the credentials on request of the page through iframe?
EDIT:
In this code, I'm trying to send the credentials automatically so that the authentication prompt doesn't show.
With basic authentication you need to render <iframe src="..."></iframe> and the browser will show you a dialog to enter the credentials.
If you construct the body at the server (i.e. in Wicket code) then you don't need an iframe, but a div.

Prevent page access via URL

Good morning everyone!
I have an application that has access control, it is working ok
But the user can write the URL in the browser and access pages that he does not have access to
Could someone help me solve this?
Below is the implementation of Filter
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filter) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession();
if (session.getAttribute("sessionUser") != null
|| req.getRequestURI().endsWith("Login.xhtml")) {
System.out.println("if");
filter.doFilter(request, response);
} else {
System.out.println("else");
HttpServletResponse res = (HttpServletResponse) response;
res.sendRedirect(req.getContextPath()+"/Login.xhtml");
}
}
Before answer i suggest you to use one security framework to control access of pages. something powerfull like spring security.
But in this case you checked only that user session is validated or not but nothing related to page or page name added to session.
You should add all user accessed page (name for example), to session as attributes after successful login and then in this filter, check what page user requested to access?
If session attributes contains that page dofilter called else redirect to access denied page.

JSF response.setHeader "Content-disposition" no popup

Just starting to learn how to do the download with jsf.
I have looked at couple other related posts. And mainly copy their code, but it seems like I did something wrong.
This is my code
public void download() throws IOException {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
response.reset(); // Some JSF component library or some Filter might have set some headers in the buffer beforehand. We want to get rid of them, else it may collide.
response.setContentType(contentType); // Check http://www.iana.org/assignments/media-types for all types. Use if necessary ServletContext#getMimeType() for auto-detection based on filename.
response.setHeader("Content-disposition", "attachment;filename=\"001.cvf\""); // The Save As popup magic is done here. You can give it any filename you want, this only won't work in MSIE, it will use current request URL as filename instead.
BufferedInputStream input = null;
BufferedOutputStream output = null;
String content =VCFHandler.getContent(profile.getFriendlist());
response.setHeader("Content-Length", String.valueOf(content.length()));
try {
InputStream stream = new ByteArrayInputStream(content.getBytes("UTF-8"));
input = new BufferedInputStream(stream);
output = new BufferedOutputStream(response.getOutputStream());
byte[] buffer = new byte[10240];
for (int length; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
output.flush();
} finally {
output.close();
input.close();
}
facesContext.responseComplete(); // Important! Else JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}
So I tried this code with debugger in eclipse. When download button is clicked, this method is called (which is what I wanted). But after all steps are finished no popup is shown in my page. Anyone have any suggestions?
BTW the content type is
private final static String contentType="text/x-vcard";
By your problem description, I'm not sure but looks like you're firing the download from an ajax request. Remove the ajax behavior for this request and try again.

Populating IAuthSession with data from the database

So I've created a custom CredentialsAuthProvider using ServiceStack as per the examples located here:
https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization
I have the authentication side of things working but I'm not sure how I populate the session with data from the database in the OnAuthenticated method. In the example they show the following:
//Fill the IAuthSession with data which you want to retrieve in the app eg:
session.FirstName = "some_firstname_from_db";
In the TryAuthenticate method I have the username/password, which I can use to authenticate the user against the database, but once it goes to the OnAuthenticated method, how/what do I use to access/retrieve the user information from the database?
I know this is an older thread but it may still be relevant because unfortunately not much has improved since Sep of 2012 in terms of availability of ServiceStack documentation, clarity of examples or even comments in the code. (#mythz: It would be very helpful if you guys could add meaningful summaries to all your classes and methods.)
I struggled with the same dilemma until I looked at the actual code of CredentialsAuthProvider (which in general is pretty much the only way to understand how things work in ServiceStack). The OnAuthenticated is called right after TryAuthenticate inside the Authenticate method, so I figured it's not necessary to make all your DB calls in OnAuthenticated as #mythz suggests in his examples. Instead I placed the code that populates the IAuthSession object right into my implementation of TryAuthenticate, like so:
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
try
{
// Use my own repo to authenticate the user.
var userRepo = authService.TryResolve<IUserRepository>();
var user = userRepo.Authenticate(userName, password);
// Populate session properties with data from my user POCO.
var session = authService.GetSession();
session.Id = user.CurrentSession.ID.ToString();
session.IsAuthenticated = true;
session.CreatedAt = DateTime.UtcNow;
session.DisplayName = session.FirstName = session.LastName = user.FullName;
session.UserAuthName = session.UserName = user.Username;
session.UserAuthId = user.ID.ToString();
}
catch (Exception ex)
{
// Log the exception, etc....
return false;
}
return true;
}
However, you still have to override OnAuthenticated in order to save the cookie in HTTP response (which I assume is required for subsequent requests from the same browser to be authenticated) because the base implementation only sets the cookie if it finds IUserAuthRepository in the IOC container, which in my case won't happen because I use my own repository. So my implementation now looks like this:
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
try
{
// Save the browser cookie.
var httpRes = authService.RequestContext.Get<IHttpResponse>();
if (httpRes != null)
{
httpRes.Cookies.AddPermanentCookie(HttpHeaders.XUserAuthId, session.UserAuthId);
}
// Save the user session object (ServiceStack stores it in the in-memory cache).
authService.SaveSession(session, SessionExpiry);
}
catch (Exception ex)
{
// Log the exception, etc....
}
}
#mythz: Please let me know if the above makes sense or not.
Another good example of a ServiceStack's CustomUserSession is in the SocialBootstrapApi project. Rather than pulling information out of the data, it extracts the information out of the UserSession and populates its own Custom User Table using the registered DB Factory resolved from the AppHost IOC:
authService.TryResolve<IDbConnectionFactory>().Run(db => db.Save(user));
Rather than using it to extract and save data from the user's session, you can also use any of your registered dependencies to fetch data and populate the session with:
public override void OnAuthenticated(
IServiceBase authService,
IAuthSession session,
IOAuthTokens tokens,
Dictionary<string, string> authInfo)
{
using (var db = authService.TryResolve<IDbConnectionFactory>().OpenDbConnection())
{
var user = db.Id<MyUser>(session.UserId);
session.FirstName = user.FirstName;
}
}

how to differentiate a new log in (new Session) and a session time out

Could someone let me know how to differentiate a new log in (new Session) and a session time out .
Only on login : user must be authenticated and redirected to a servlet to load user details (on other screnarios user must not be redirected to the servlet)
and on timeout user must be redirected to the timeout page.
To identify a new session (user not logged in):
-- Session attributes cannot be used since the session becomes null on timeout.
-- Setting cookies for session management didnt work.
The cookies are getting removed for the current session
Cookie cookie = new Cookie("activeSession", null);
cookie.setMaxAge(0);
cookie.setPath("/");
cookie.setValue("");
httpServletResponse.addCookie(cookie);
getCookieValue(httpServletRequest , "activeSession"); returns null
public static String getCookieValue(HttpServletRequest request, String name) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie != null && name.equals(cookie.getName())) {
return cookie.getValue();
}
}
}
return null;
}
After logout or Timeout (session is invalidated) when user logs in and a new session is created.
The cookies that were removed in the previous sessions reappears with the preset values.
getCookieValue(httpServletRequest , "activeSession") returns a value;
If I use the below approach it works for the 1 st login attempt.
After the first login session has timedout ,the filter redirects to timeout page.
The actual problem arises when user accesses the application in the same window after timeout.
public void doFilter(ServletRequest request, ServletResponse response,FilterChain filterChain) throws IOException,
{ if ((request instanceof HttpServletRequest)
&& (response instanceof HttpServletResponse)) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
//Check for a new login
if (httpServletRequest.getSession(false) == null && httpServletRequest.getRequestedSessionId()==null)
{
// Create a new session
httpServletRequest.getSession();
//Redirect to servlet on 1 st login to fetch details from DB
httpRequest.getRequestDispatcher("/loginServlet").forward(request,response);
}else{
//validate active or timedout sessions.
boolean isSessionValid = (httpServletRequest.getRequestedSessionId() != null) && !httpServletRequest.isRequestedSessionIdValid();
if(isSessionValid)
{
httpServletResponse.sendRedirect(getTimeoutPage());
}
}
}
filterChain.doFilter(request, response);
}
Therefore the details are not fetched from DB and the page is not loaded correctly.
Browser:IE 8
Server : Weblogic server
Your cookie approach is unnecessary and technically invalid. A max age of 0 makes it to expire immediately when the response is processed. But anyway, you don't need an additional cookie. The HttpSession is by itself already backed by a cookie and the Servlet API already offers methods to check the one and other. Just store the logged-in user as an attribute of the HttpSession (which can in turn be a session scoped JSF managed bean).
The following example should do, assuming that you've stored the logged-in user as a property of a session scoped JSF managed bean with the managed bean name "auth".
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
Authenticator auth = (Authenticator) req.getSession().getAttribute("auth");
if (req.getRequestedSessionId() != null && !req.isRequestedSessionIdValid()) {
res.sendRedirect(req.getContextPath() + "/timeout.xhtml");
} else if (auth == null || !auth.isLoggedIn()) {
res.sendRedirect(req.getContextPath() + "/login.xhtml");
} else {
chain.doFilter(request, response);
}
}

Resources