Good day,
When a user hit specific url with an extension on html, I want to validate if user has logged in. If the user is not logged in, I want to redirect them to my custom login page (this part is done). Else, I want to do nothing - meaning the current page that they are on, should continue being displayed.
I want this to meet client requirements (the default AEM login page should stay as is.
Scenario
The page is /content/mysite/page.html
If I am not logged in, I should be redirected to /content/mysite/login.html
If I am logged in, I should still see this page : /content/mysite/page.html
Now, my problem comes when I am logged in. Instead of seeing content of the page : /content/mysite/page.html, there page is simply blank. There are no contents to be displayed.
Maybe I do not get the concepts of servlets or I do not know how to handle this kind of problem.
Please help resolve this or suggest another route to handle this
Here is my the code I have so far:
package com.company.patientsportal.core.auth;
import java.io.IOException;
import java.util.Map;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.servlet.ServletException;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.engine.SlingRequestProcessor;
#Service
#SlingServlet(resourceTypes={"patientsportal/components/structure/page"}, selectors="html", methods = "GET", metatype=true, description="My Authentication Verifier")
#Properties
(
{
#Property(name="login.form", description="The form on which the user to enter authentication credentials.", value="")
}
)
public class CheckAuthentication extends SlingAllMethodsServlet
{
/**
*
*/
private static final long serialVersionUID = 8552708551560032677L;
private Map<String, Object> redirects;
#Reference
private Repository repository;
#Reference
private SlingRequestProcessor requestProcessor;
#Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException
{
ResourceResolver resolver = request.getResourceResolver();
Session session = resolver.adaptTo(Session.class);
String userId = session.getUserID();
String url = request.getRequestPathInfo().getResourcePath();
url = url.substring(0, url.lastIndexOf("/")) + ".html";
if (String.valueOf(userId) == null || (String.valueOf(userId) != null ? String.valueOf(userId).equals("anonymous") : false))
{
String loginForm = getLoginForm("login.form");
if (loginForm != null)
{
response.sendRedirect(loginForm + "?url=" + url);
}
else
{
response.sendRedirect("/content/patientsportal/login.html?url=" + url);
}
}
else
{
//Do nothing or something in the else
//So far, do nothing does not work. It returns blank page even if I do not include the else part
}
}
private String getLoginForm(String loginForm)
{
if (redirects != null)
{
loginForm = (String) redirects.get(loginForm);
return loginForm;
}
return null;
}
#Activate
protected void activate(Map<String, Object> properties)
{
redirects = properties;
}
}
The ideal way of implementing login functionality is to either use the OOTB AEM authentication handler or implement Sling AuthenticationHandler and extending DefaultAuthenticationFeedbackHandler. You can find the code references to implement in lot of blogs -
acs-aem-samples
How to Create Custom Authentication Handler in CQ
After you have implemented this and have created/configured your own login page /form, you need to setup CUG on the pages that are to be exposed only to a logged in user. The details around it are available in AEM documentation here
Related
I am new to MongoDB Mlab, which means not familiar with how to use it and how to connect it with a DAO file. And I encounter a technical issue on SERVLET. Firstly, I try to extract data from MongoDB mlab to get an email & password of a user for my login page. And I also capture the email & password entered by a user on login JSP page by using "request.getParameter("")" method. These two points work fine because I already tested them. More info about my issue is that when I try to extract email and password from MongoDB mlab, I store these two parameters into a user object, and store the user object into an ArrayList. Then return this Arraylist to the login Servlet. Using for-each loop to traversal this list. I put the codes below.
When I try to enter an email and password on the login page, this is the result I encountered
how can I solve it
FDao.java
package Dao;
import static com.sun.corba.se.spi.presentation.rmi.StubAdapter.request;
import java.net.UnknownHostException;
import java.sql.*;
import java.util.*;
import javax.servlet.RequestDispatcher;
import model.Book;
import model.Staff;
import model.User;
import org.bson.Document;
public class FDao {
public List<User> checkLogin() throws UnknownHostException {
Iterator it = DB.getDB().getCollection("users").find().iterator();
List<User> aUser = new ArrayList();
while(it.hasNext()){
Document o = (Document) it.next();
aUser.add(new User(o.getString("email"), o.getString("password")));
}
return aUser;
}
}
LoginServlet.java(I capture string email and string password from login JSP page)
#WebServlet("/Login")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
super();
}
FDao userDao = new FDao();
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
String email = request.getParameter("email");
String password = request.getParameter("pass");
List<User> users = new ArrayList();
users = userDao.checkLogin();
for (User user : users) {
if (email.equals(user.getEmail()) && password.equals(user.getPassword()) ) {
//HttpSession session = request.getSession();
//session.setAttribute("user", user);
request.getRequestDispatcher("/home.jsp").include(request, response); //the problem looks like appeared in this line of code
//out.println("Hello World");
} else {
//String message = "Your account does not exist in out database!";
//request.setAttribute("message", message); //message is object
request.getRequestDispatcher("/Login.jsp").include(request, response);//the problem looks like appeared in this line of code
//out.println("Nothing");
}
break;
}
}
}
I am working with small app that uses spring-hibernate but I am a newcomer to field of spring MVC, I have some questions:
1) using single controller for multiple pages is good practice or should I create separate cont. class for each page.
2) I don't want to use form tag of spring I'm using html forms.
My controller is as follows:
package com.servlets.controllers;
import com.utils.generalUtils;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class signin{
#RequestMapping(value = "/login", method={RequestMethod.POST,RequestMethod.GET})
public ModelAndView loginForm(HttpServletRequest req,HttpServletResponse response){
HashMap<String,String> lsMsg = new HashMap<String,String>();
lsMsg = generalUtils.getInstance().LoginCheck(req);
for (Map.Entry<String, String> entry : lsMsg.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(" key -- "+key+" value -- "+value);
}
if((lsMsg.get("Authorized")).equals("true")){
return new ModelAndView("landing", "message", lsMsg);
}
return new ModelAndView("login", "message", lsMsg);
}
#RequestMapping(value = "/fergot", method={RequestMethod.POST,RequestMethod.GET})
public ModelAndView fergotForm(HttpServletRequest req) { // Not implemented yet
HashMap<String,String> lsMsg = new HashMap<String,String>();
return new ModelAndView("fergot", "message", lsMsg);
}
#RequestMapping("/register")
public ModelAndView registerForm(HttpServletRequest req,HttpServletResponse response) throws IOException{
HashMap<String,String> lsMsgs = new HashMap<String,String>();
lsMsgs.put("Authorized", "false");
lsMsgs = generalUtils.getInstance().addUser(req);
if((lsMsgs.get("Authorized")).equals("true")){
response.sendRedirect("login.html");
}
return new ModelAndView("register", "message", lsMsgs);
}
}
1) Both way are ok. But you want best practise, so my suggestion is create separate controller class for each page . This is common choice in most cases. On the other hand, if your app is very very small, even if you using single controller is also not a big problem.
Chose which way's core problem is which way can maintain easier in the future and which way is more readable for others.
2) You say you don't want to use spring form tag, ofcourse you can. Take it easy, You can not use any part of spring you don't want to use, it is ok.
i want to show online users using this servlet ......
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.chatapp.useroperation.Client;
#WebServlet(name = "onlineUsersServlet", urlPatterns = { "/getOnlineUsersList" })
public class ListOfOnlineUsers extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String commaSepeparatedStr ="";
ServletContext appScope = request.getServletContext();
String channel = request.getParameter("channel");
final Map<String, List<Client>> clients = (Map<String, List<Client>>) appScope.getAttribute(LoginServlet.CLIENTS);
System.out.println(clients);
if(clients.size()> 0){
final List<Client> onlineClients = clients.get(channel);
if(onlineClients !=null){
for (Client client : onlineClients) {
if(commaSepeparatedStr.equals("") ){
commaSepeparatedStr = client.getUserName();
}else{
commaSepeparatedStr =commaSepeparatedStr+","+ client.getUserName();
}
}
}
}
response.getWriter().write(commaSepeparatedStr);
response.flushBuffer();
}
}
how can i pass value to this servlet from a jsp so that it store the username in its list......is it possible to put value in that servlet from session.
in your jsp do something like this:
<form action="/YOURWEBAPPNAME/onlineUsersServlet/getOnlineUsersList" method="get">
<input type="text" name="test" value="Hello World">
<input type="submit" value="Send">
</form>
in you doGet method do this:
String userInput = request.getParameter("test");
and feel free using that stuff.
put that stuff in the session with:
request.getSession(false).setAttribute("input",userInput);
and read it with:
String lInput = (String) request.getSession(false).getAttribute("input");
If you want to Store a Value from a session to a servlet, just attach an attribute to the Session;
During Login, get the username and store the value into the Session;
HttpSession sess = request.getSession();//Create new Session
//Get the username from login input
String username = request.getParameter("name");
//Attach the name to the Session.
sess.setAttribute("username", username);
Get the value anytime as long as the session is active.
HttpSession sess = request.getSession(false);//Use the current Session
//Get the value fron the Session
String username = (String) sess.getAttribute("username");//get the Attribute Username
You need to have Attached the Attribute to the Session before you can get it this way.
There are variables with a different scope that you can, or not, access from different places in your code. In JavaEE there are variables with request, session and application scope.
The request scope means that you can set it and use it in all your classes for the current request and that's what you seem to need right now.
I'm sorry I can't help you more right now but with this info Google or the SO search box should be your friend. I'll add details later.
Edit -
Stefan beike's answer has these details I'm talking about.
Is there a good way to get the logged in user count in a Java web application that is running in a cluster?
I wrote a simple HttpSessionListener with a static field, but I suppose this doesn't work in cluster. I can see there is a Spring Security solution, but I read in some forums that this is still not ok in cluster.
The product in which I have to implement this user count is trying to be application server independent, currently we support Tomcat, Weblogic and JBoss. At the moment I need a solution for Weblogic 10.3 clusters.
You can maintain the counter in database which will work in cluster env.
A simple tutorial to demonstrate how to determine active users / sessions in a Java Web Application.
package com.hubberspot.javaee.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
#WebListener
public class OnlineUsersCounter implements HttpSessionListener {
private static int numberOfUsersOnline;
public OnlineUsersCounter() {
numberOfUsersOnline = 0;
}
public static int getNumberOfUsersOnline() {
return numberOfUsersOnline;
}
public void sessionCreated(HttpSessionEvent event) {
System.out.println("Session created by Id : " + event.getSession().getId());
synchronized (this) {
numberOfUsersOnline++;
}
}
public void sessionDestroyed(HttpSessionEvent event) {
System.out.println("Session destroyed by Id : " + event.getSession().getId());
synchronized (this) {
numberOfUsersOnline--;
}
}
}
Running the below servlet on three different browsers will provide output as : (see fig below)
package com.hubberspot.javaee;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.hubberspot.javaee.listener.OnlineUsersCounter;
// #WebServlet annotation has a initParams field which takes
// in initialization parameters for a servlet.
// #WebInitParam annotation takes in a name and value for the
// initialization parameters for the current Servlet.
#WebServlet(name = "HelloWorldServlet" , urlPatterns = { "/HelloWorldServlet" }
, initParams = { #WebInitParam(name = "user" , value = "Jonty") })
public class HelloWorldServlet extends HttpServlet {
protected void doGet(
HttpServletRequest request,
HttpServletResponse response
) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
// sessionCreated method gets executed
HttpSession session = request.getSession();
session.setMaxInactiveInterval(60);
try {
out.println("<html>");
out.println("<body>");
out.println("<h2>Number of Users Online : "
+ OnlineUsersCounter.getNumberOfUsersOnline()
+ "</h2>");
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}
}
Output of the program :
Eclipse Browser ->
Firefox Browser ->
Internet Explorer Browser ->
Console Output ->
For more: http://www.hubberspot.com/2013/09/how-to-determine-active-users-sessions.html
what options do I have to profile a page request in a spring mvc app?
I want to get a breakdown of how long the page request takes, along with the various stages like how long it takes to render the freemarker template, hibernate db calls, etc.
We just accomplished something similar with an interceptor and a custom tag. This solution is "light" enough to be used in production, presents its data as HTML comments at the bottom of the response, and allows you to opt into the more verbose logging with a request parameter. You apply the interceptor below to all request paths you want to profile, and you add the custom tag to the bottom of the desired pages. The placement of the custom tag is important; it should be invoked as close to the end of request processing as possible, as it's only aware of time spent (and objects loaded) prior to its invocation.
package com.foo.web.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class PageGenerationTimeInterceptor extends HandlerInterceptorAdapter {
public static final String PAGE_START_TIME = "page_start_time";
public static final String PAGE_GENERATION_TIME = "page_generation_time";
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
request.setAttribute(PAGE_START_TIME, new Long(System.currentTimeMillis()));
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
Long startTime = (Long) request.getAttribute(PAGE_START_TIME);
if (startTime != null) {
request.setAttribute(PAGE_GENERATION_TIME, new Long(System.currentTimeMillis() - startTime.longValue()));
}
}
}
The custom tag looks for the request attributes, and uses them to compute the handler time, the view time, and the total time. It can also query the current Hibernate session for first-level cache statistics, which can shed some light on how many objects were loaded by the handler and view. If you don't need the Hibernate information, you can delete the big if block.
package com.foo.web.taglib;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.servlet.ServletContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TryCatchFinally;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.engine.CollectionKey;
import org.hibernate.engine.EntityKey;
import org.hibernate.stat.SessionStatistics;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.tags.RequestContextAwareTag;
import com.foo.web.interceptor.PageGenerationTimeInterceptor;
public class PageInfoTag extends RequestContextAwareTag implements TryCatchFinally {
private static final long serialVersionUID = -8448960221093136401L;
private static final Logger LOGGER = LogManager.getLogger(PageInfoTag.class);
public static final String SESSION_STATS_PARAM_NAME = "PageInfoTag.SessionStats";
#Override
public int doStartTagInternal() throws JspException {
try {
JspWriter out = pageContext.getOut();
Long startTime = (Long)pageContext.getRequest().getAttribute(PageGenerationTimeInterceptor.PAGE_START_TIME);
Long handlerTime = (Long)pageContext.getRequest().getAttribute(PageGenerationTimeInterceptor.PAGE_GENERATION_TIME);
if (startTime != null && handlerTime != null) {
long responseTime = System.currentTimeMillis() - startTime.longValue();
long viewTime = responseTime - handlerTime;
out.append(String.format("<!-- total: %dms, handler: %dms, view: %dms -->", responseTime, handlerTime, viewTime));
}
if (ServletRequestUtils.getBooleanParameter(pageContext.getRequest(), SESSION_STATS_PARAM_NAME, false)) {
//write another long HTML comment with information about contents of Hibernate first-level cache
ServletContext servletContext = pageContext.getServletContext();
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
String[] beans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context,
SessionFactory.class, false, false);
if (beans.length > 0) {
SessionFactory sessionFactory = (SessionFactory) context.getBean(beans[0]);
Session session = sessionFactory.getCurrentSession();
SessionStatistics stats = session.getStatistics();
Map<String, NamedCount> entityHistogram = new HashMap<String, NamedCount>();
out.append("\n<!-- session statistics:\n");
out.append("\tObject keys (").append(String.valueOf(stats.getEntityCount())).append("):\n");
for (Object obj: stats.getEntityKeys()) {
EntityKey key = (EntityKey)obj;
out.append("\t\t").append(key.getEntityName()).append("#").append(key.getIdentifier().toString()).append("\n");
increment(entityHistogram, key.getEntityName());
}
out.append("\tObject key histogram:\n");
SortedSet<NamedCount> orderedEntityHistogram = new TreeSet<NamedCount>(entityHistogram.values());
for (NamedCount entry: orderedEntityHistogram) {
out.append("\t\t").append(entry.name).append(": ").append(String.valueOf(entry.count)).append("\n");
}
Map<String, NamedCount> collectionHistogram = new HashMap<String, NamedCount>();
out.append("\tCollection keys (").append(String.valueOf(stats.getCollectionCount())).append("):\n");
for (Object obj: stats.getCollectionKeys()) {
CollectionKey key = (CollectionKey)obj;
out.append("\t\t").append(key.getRole()).append("#").append(key.getKey().toString()).append("\n");
increment(collectionHistogram, key.getRole());
}
out.append("\tCollection key histogram:\n");
SortedSet<NamedCount> orderedCollectionHistogram = new TreeSet<NamedCount>(collectionHistogram.values());
for (NamedCount entry: orderedCollectionHistogram) {
out.append("\t\t").append(entry.name).append(": ").append(String.valueOf(entry.count)).append("\n");
}
out.append("-->");
}
}
} catch (IOException e) {
LOGGER.error("Unable to write page info tag");
throw new RuntimeException(e);
}
return Tag.EVAL_BODY_INCLUDE;
}
protected void increment(Map<String, NamedCount> histogram, String key) {
NamedCount count = histogram.get(key);
if (count == null) {
count = new NamedCount(key);
histogram.put(key, count);
}
count.count++;
}
class NamedCount implements Comparable<NamedCount> {
public String name;
public int count;
public NamedCount(String name) {
this.name = name;
count = 0;
}
#Override
public int compareTo(NamedCount other) {
//descending count, ascending name
int compared = other.count - this.count;
if (compared == 0) {
compared = this.name.compareTo(other.name);
}
return compared;
}
}
}
Take a look here:
Profiling with Eclipse and remote profile agents on Linux
Tutorial: Profiling with TPTP and Tomcat
An introduction to profiling Java applications using TPTP
TPTP = Eclipse Test and Performance Tools Platform
More links to the stack:
Open Source Profilers in Java