I am currently trying to complete a login system using jsp and servlets.I have my register and login validation working.
I wish to link to a welcome page following login to display the user profile information.
I had, just for testing purposes, a response.sendRedirect(welcome.jsp) which redirected following a successful login by the login servlet.
Now, to display the profile info on this welcome page I was going to use a servlet to gather the info from the database and render it to the the browser using a printwriter.
How do I call this servlet successfully from the loginservlet to run the doPost() method?
Or is there a better way of doing it?
Thank you for your time.
(For simplicity, I was just trying to get a basic webpage to appear first to make sure this was working I will have no problem with the database side of things once I get this going)
LOGIN SERVLET:
package logon;
import java.io.IOException;
import javax.servlet.ServletException;
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;
#WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try
{
System.out.println("In the Login Servlet");
User user = new User();
user.setEmail(request.getParameter("email"));
user.setPassword(request.getParameter("password"));
LoginDAO.login(user);
if(user.isValid())
{
HttpSession session = request.getSession(true);
session.setAttribute("currentSessionUser",user);
session.setAttribute("currentSessionUserEmail", user.getEmail());
response.sendRedirect("WelcomeServlet");
}else
response.sendRedirect("LoginFailure.html");
} catch (Throwable exc)
{
System.out.println(exc);
}
}
}
WELCOME SERVLET:
package logon;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet("/WelcomeServlet")
public class WelcomeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public WelcomeServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out=response.getWriter();
out.print("<html>"+"<head>"+"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">");
out.print("<title>Welcome</title>");
out.print("</head>"+"<body>");
out.print("Welcome to the welcome page!!!");
out.print("</body>"+"</html>");
}
}
You can't redirect using POST, only using GET. Since you're just displaying HTML in WelcomeServlet move the code from doPost to doGet, or make the one call the other, which simply makes them both do the same thing.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doPost(request, response);
}
Also, it would be better to use a JSP than to out.print a bunch of HTML inside a servlet. See the info page for servlets.
Plus, obviously your welcome page needs to read the attribute currentSessionUser from the session and make sure its not null to see if the user is really logged in or not. Otherwise if a user knows the address of the welcome page they can just bypass your login check as you have it now.
Your problem is that you have currently implemented your Servlet to respond to the wrong HTTP verb.
You'll notice that the servlet has as doPost and a doGet method. As you might expect these map onto HTTP GET and HTTP POST requests. Your current problem stems from the fact that you have implemented the doPost method in your WelcomeServlet therefore expecting a POST request, when it will actually be serving a GET request.
Speaking very crudely, you can think of GET requests as read operations and POST requests as write operations. So when you submit a form to save some data, this is typically handled a POST request. You are basically asking to write data to a database or session. When you load a web page, this is typically handled as a GET request. You are simply asking to read the data.
Again simplifying, but re-directs are typically GET requests. Therefore your Servlet will need to implement the doGet() method to respond to the browsers GET request after it is re-directed.
Related
I have built a single page webapplication using Angular on the frontend and Spring on the backend. Its a community website and i want to be able to ban misbehaving users the spring way. I have searched stackoverflow to see if there is a thread about this but i could find none.
My attempt to build this functionality is by creating a custom webfilter that filters all incoming requests and checks whether the ip address of the requester is in the blocked ip list. If not then the request gets forwarded, but if it is on the list then an error response is sent back instead.
Here is the code of the filter and an implementing interface:
package RequestPreprocessors;
import DAOs.BanDao;
import Interfaces.IpAddressExtractor;
import Services.ModeratorService;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;
import java.util.logging.Logger;
#WebFilter("/*")
public class IpAddressFilter implements Filter, IpAddressExtractor {
private static final Logger log = Logger.getLogger("IpAddressFilter.class");
private Set<String> blockedIpAddresses;
#Autowired
private ModeratorService moderatorService;
#PostConstruct
private void loadBlockedIpAddresses(){
blockedIpAddresses = moderatorService.getBlockedIpAddresses();
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
String clientIpAddress = getClientIP((HttpServletRequest) servletRequest);
log.info("ip " + clientIpAddress + " is requesting " + httpServletRequest.getRequestURI());
if(blockedIpAddresses.contains(clientIpAddress)) {
log.info(clientIpAddress + " is currently on the banlist, aborting request...");
httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
}
filterChain.doFilter(servletRequest, servletResponse);
}
#Override
public void destroy() {
}
}
Here is the code of the implementing interface
public interface IpAddressExtractor {
public default String getClientIP(HttpServletRequest request) {
String xfHeader = request.getHeader("X-Forwarded-For");
if (xfHeader == null){
return request.getRemoteAddr();
}
return xfHeader.split(",")[0]; // voor als ie achter een proxy zit
}
}
This should work but i don't think sending a simple http status code is very elegant, i would like to be able to send back a message explaining to the user that he/she is in fact banned.
So my question is; How do i ban a user from a spring web application effectively. And with effectively i mean being able to send an error message back to the single page app that can then be displayed to the user. I would also like to know if this is the best way to deny banned users access from the REST api. I would like to know if there are different more effective ways to accomplish this.
Thank you
EDIT: This is the tutorial i used to create the majority of the code https://www.baeldung.com/java-web-app-without-web-xml
Effective banning is a co-operative effort between your application doing the detection and the operating system implementing the block. If you are deploying on to Linux then an effective strategy is this:
Log an easily parseable message to an audit log file that says the user is to be banned and include the IP address. The HTTP response to the offender can include a suitable 'goodbye' message.
Install and configure fail2ban to parse your log files and implement the ban. It works by making local modifications to the firewall rules to prevent the offender even making a network connection to your server.
Is it possible for a java servlet to call the function that is in another java servlet? And if it is possible, can you show me a simple example of how to do it?
Thank you in advance
Calling a servlet directly from another servlet is not recommended and considered bad practice because servlet instances are managed by the servlet container. You should follow the separation of concerns principle.
The servlets are responsible for the interface to clients only and shouldn't contain business logic. Put your business logic in a separate layer (e.g. classes in another package) and call it from the servlets only. So the business classes are responsible for the actual internal data and transformations and the servlets are responsible for different views to the outside.
Several options.
Making it static one way (I do not prefer).
Create a Class and supply required params and create instance in each servlet.
Somewhat hackish way:
RequestDispatcher dispatcher = request.getRequestDispatcher("/someServletOfYours");
dispatcher.forward(request, response);
Now, implement the method of yours in doPost of your "someServletOfYours" class. In case you need to pass parameters, call the setAttribute method of ServletRequest, and fetch parameters from the request in your next servlet. From "someServletOfYourrs" you can redirect back to your original servlet. It will imitate a method call by means of http.
Servlet1
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Servlet1
*/
#WebServlet("/Servlet1")
public class Servlet1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
Servlet2 s = new Servlet2();
s.CreateUser();
response.getWriter().append("Served at: ").append(request.getContextPath());
}
}
Servlet2
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Servlet1
*/
#WebServlet("/Servlet2")
public class Servlet2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
public void CreateUser() throws FileNotFoundException{
System.out.println("Create Users...");
}
}
Output :
I like to run a servlet on a tomcat server but it gives the error as above.Also when i put ajax request on the servlet it did not working through index.jsp.Please help me friends.
also explain briefly because I am at the starting level of servlet.
import java.sql.Connection;
java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import com.mysql.jdbc.Driver;
import java.util.Arrays;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MySQLAccess extends HttpServlet
{
public void getRows(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException
{
String a="";
PrintWriter out = response.getWriter();
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/sankar?" + "user=root");
Statement statement = connection.createStatement();
ResultSet resultSet = statement
.executeQuery("SELECT * FROM sankar.datas");
a=resultSet.getString("name");
}
catch (Exception e)
{
e.printStackTrace();
}
out.println(a);
}
}
In order to accept the GET request, you need to override the doGet method in your MySQLAccess servlet class. Considering the code, you may just have to replace the name of your getRows method to doGet. From javadocs
HttpServlet class provides an abstract class to be subclassed to
create an HTTP servlet suitable for a Web site. A subclass of
HttpServlet must override at least one method, usually one of these:
doGet, if the servlet supports HTTP GET requests
doPost, for HTTP POST requests
doPut, for HTTP PUT requests
doDelete, for HTTP DELETE requests
You need the doGet-Method like so:
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// your code
}
This method is called from the server (tomcat container more specifically) when a GET request is sent to the servlet.
If you wish to use POST you need to implement the doPost(...)method, btw.
I am working on a simple program redirection by making some calls to a servlet. However, for some reason, I am continuously getting a 404 error every time I try to construct the code in this particular project build.
It may be of note that I am building this project in Eclipse and am using Apache Tomcat.
here is my coding....
HTML first:
To save some aggrivation, this is the particular snippet on where the problems arise. My connection to the MySQL database along with the database reads are operating perfectly fine.
<form action="objectServer" method="get">
<select name="choice">
<% while (rs.next()){ %>
<option value="<%=rs.getString(2) %>"><%=rs.getString(2) %></option>
<% }
MysqlConnection.close(connect);
%>
</select>
<br />
<input type="submit" value="View the Descrition!" />
</form>
Java code:
The first is a simple java class that validates whether an item has been selected and acts to help redirect.
package com.program.service;
public class Service {
public boolean redirect(String selected){
if( (selected == null) || (selected == "") ){
return false;
} else {
return true;
}
}
}
And finally, the servlet itself.
package com.program.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.wines.service.Service;
#WebServlet("/objectServer")
public class InfoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String selected = request.getParameter("choice");
Service service = new Service();
boolean redirector = service.redirect(selected);
if(redirector){
response.sendRedirect("next_page.jsp");
} else {
response.sendRedirect("this_page.jsp");
}
}
}
As one can see, this is a REALLY simple program that should be redirecting to the next page, but for some reason I am missing something that I just cannot see at this moment. I don't don't know whether it's an issue with my coding, my server, or something else I could have missed. As a note, the web.xml has not been programmed in this particular application as of yet.
Depending on your setup, your jsp's are most likely can be only accessed through Servlets. In this case, you will need to use "forward" instead of "redirect". Please understand the differences between "forward" and "redirect". Here is a good read: Forward versus redirect
Example Forward:
RequestDispatcher dispatcher = aRequest.getRequestDispatcher("this_page.jsp");
dispatcher.forward(aRequest, aResponse);
Example redirect:
response.sendRedirect(absoluteOrRelativeURL); // e.g absoluteOrRelativeURL= "objectServer"
if your JSP pages are resides under the WEB-INF, you cannot redirect to the JSP page. this is because the content under the WEB-INFare restricted from the direct access. therefore you have to forward the request for that resource. that can be done by modifying you method as follows. ( i have assumed that your jsp pages are resides directly under the WEB-INF directory)
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String selected = request.getParameter("choice");
Service service = new Service();
boolean redirector = service.redirect(selected);
if(redirector){
request.getRequestDispatcher("WEB-INF/next_page.jsp").forward(request,response);
} else {
request.getRequestDispatcher("WEB-INF/this_page.jsp").forward(request,response);
}
}
further more, if you wish to make a ridirect for particular resource, make sure to do the redirect for a servlet mapping. you cannot make a redirect for a particular resource resides under the WEB-INF directory.
A request to an Action can be validated using the Interceptors. Also, Direct request to a JSP page can be avoided using an empty action declaration. It is something like this;
<action name="home" >
<result>home.jsp</result>
</action>
I want to validate this calling to the JSP page. As I feel that a simple approach can be adding an Action (ActionSupport) with an Interceptor which checks the action name( and do some validation using session etc). But I've a doubt that whether it reduces the performance,because that action class doesn't do anything and just execute its execute() only(useless task...), and where there should be an empty Action .(BUT: as I ve read some docs on Struts2, it is said that even though we don't add an Action calss,the framework itself adds and action class which returns "success" therefore,adding an action class or not ourselves, doesn't affect newly )
Any way, I d like to know what your best approaches are to validate or authorized access to some JSP pages.( number of pages can be many.. not only to one jsp page)
Added:
Example:
Lets say that, there are some restricted pages where all users can't have access,for example user's account page can be visited only to logged in users.There can be more such type of pages. If a request comes to a such page,the user has to be validated.Then, if the request comes through a empty/anonymous action (as explained in above code snip -only action name-no real class) how to validate such requests to JSP pages? Should an action class be used for this?
If your attention is to secure some part of your application so as only Authenticated as well authorize use can access that part, than you have two option
Use an interceptor based authentication
User a security API like Spring -security
Interceptor based authentication is quite easy. here is an example how to do this, but such authentication is not recommended for a production based and real life application since its really a very simple case.
if you are looking for a complete authentication system, i suggest you to look at Spring security.Its quite easy and configurable, all you need to tell the underlying spring mechanism which all areas and under secure tag and Spring security will intercept them before your action get called and only successful and authorize action will get called by spring security.
//This is for authorization
package com.kogent.action;
import java.io.IOException;
import java.util.List;
import java.util.regex.Pattern;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
import org.apache.struts2.dispatcher.ng.InitOperations;
import org.apache.struts2.dispatcher.ng.PrepareOperations;
import org.apache.struts2.dispatcher.ng.filter.FilterHostConfig;
import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
public class SessionController extends StrutsPrepareAndExecuteFilter {
protected PrepareOperations prepare;
protected ExecuteOperations execute;
protected List<Pattern> excludedPatterns = null;
public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();
try {
FilterHostConfig config = new FilterHostConfig(filterConfig);
init.initLogging(config);
Dispatcher dispatcher = init.initDispatcher(config);
init.initStaticContentLoader(config, dispatcher);
prepare = new PrepareOperations(filterConfig.getServletContext(),
dispatcher);
execute = new ExecuteOperations(filterConfig.getServletContext(),
dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
postInit(dispatcher, filterConfig);
} finally {
init.cleanup();
}
}
/**
* Callback for post initialization
*/
protected void postInit(Dispatcher dispatcher, FilterConfig filterConfig) {
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
prepare.setEncodingAndLocale(request, response);
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
if (excludedPatterns != null
&& prepare.isUrlExcluded(request, excludedPatterns)) {
chain.doFilter(request, response);
} else {
request = prepare.wrapRequest(request);
ActionMapping mapping = prepare.findActionMapping(request,
response, true);
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(
request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
//here you have to identify the whether the user have access to requested resource or not
//allow him if he was access.
//if(someCondition)
execute.executeAction(request, response, mapping);
//else{
//redirect the user how do you want it to be.
ActionMapping modfiedActionMapping = new ActionMapping();
modfiedActionMapping.setName("someActionName");
modfiedActionMapping.setNamespace("someNameSpace");
execute.executeAction(request, response, modfiedActionMapping);
//}
}
}
} finally {
prepare.cleanupRequest(request);
}
}
public void destroy() {
prepare.cleanupDispatcher();
}
}
<filter>
<filter-name>struts2</filter-name>
<filter-class>Point to your customized filter</filter-class>
</filter>