Filters not working properly - servlets

I made two filters for my auction web application. I implemented two filters, the first which performs simple logging operations, and the second, which check if the user is authorized to access a particular resource.
The troubles is that These filters work correctly only the first time I connect to the website. Infact it displays the name of the the user in the toolbar, and this happens only if you logged in correctly. Afterwards, I log out and I repeat the process, but the second filter does not work at all.
I put println statements to check if the filters are actually executed, but it isn't the case. The first filter works constantly. The strange part arises when I change the xml mapping. Infact, when I take the mapping out for both filters, the first filter continues working! I went nuts all day yesterday trying to understand this.
Weirder yet, If I rewrite the xml mapping for the filters, they work both for the first log in process, but then, once I log out and repeat the operation, the log in filter doesnt work anymore. To make my web application I am just JAVA7, netbeans 7.2 and Tomcat 7. I fear that this may be a bug with the Netbeans IDEA, but I am not sure.
The xml mapping is the following:
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<filter>
<filter-name>FiltroLoggingFumettopoli</filter-name>
<filter-class>Filtri.FiltroLoggingFumettopoli</filter-class>
</filter>
<filter-mapping>
<filter-name>FiltroLoggingFumettopoli</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter>
<filter-name>FiltroLogin</filter-name>
<filter-class>Filtri.FiltroLogin</filter-class>
</filter>
<filter-mapping>
<filter-name>FiltroLogin</filter-name>
<url-pattern>/Registrato/*</url-pattern>
<servlet-name>IlMioConto</servlet-name>
<servlet-name>Vendi</servlet-name>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>**
Here is the first filter which does the logging in the log fil:
private void doBeforeProcessing(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if (debug) {
log("FiltroLoggingFumettopoli:DoBeforeProcessing");
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
this.log(httpRequest.getRemoteHost()+" is trying to access page: "+httpRequest.getRequestURL()+
" il "+TimeUtility.ottieniDataOra()+". "+filterConfig.getFilterName());
System.out.println("FILTRO FILE DI LOG----> LOGGING OCCURED IN LOG FILE: "
+httpRequest.getRequestURL()+" il "+TimeUtility.ottieniDataOra()+". "+filterConfig.getFilterName());
}
private void doAfterProcessing(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if (debug) {
log("FiltroLoggingFumettopoli:DoAfterProcessing");
}
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
doBeforeProcessing(request, response);
Throwable problem = null;
try {
chain.doFilter(request, response);
} catch (Throwable t) {
problem = t;
t.printStackTrace();
}
doAfterProcessing(request, response);
if (problem != null) {
if (problem instanceof ServletException) {
throw (ServletException) problem;
}
if (problem instanceof IOException) {
throw (IOException) problem;
}
sendProcessingError(problem, response);
}
}
here is the filter which checks if it is an authorized user who wants access to the resources that are contained in the Registrato folder, and a few servlets:
public class FiltroLogin implements Filter
{
private FilterConfig filterConfig = null;
public void init(FilterConfig filterConfig)
{
this.filterConfig = filterConfig;
}
public void doFilter(ServletRequest request,ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpSession sessione = httpRequest.getSession();
ServletContext sc = filterConfig.getServletContext();
String filterName = filterConfig.getFilterName();
String servletPath = "Servlet path: " + httpRequest.getServletPath();
String url ="";
Utente user = null;
user = (Utente) sessione.getAttribute("utente");
if(user == null){
Cookie[] cookies =httpRequest.getCookies();
String email = CookieUtility.ottieniValoreCookie(cookies, "userCookie");
if(email.equalsIgnoreCase("")){
System.out.println("FILTRO LOGIN----->NESSUN COOKIE TROVATO!");
System.out.println("FILTRO LOGIN----->SERVLET CONTEXT: "+sc.getContextPath());
url ="/MostraInserzioni";
httpResponse.sendRedirect(sc.getContextPath()+url);
return;
}
else{
System.out.println("FILTRO LOGIN----->COOKIE TROVATO: "+email);
user = UtenteSql.cercaUtente(email);
System.out.println("FILTRO LOGIN----->UTENTE TROVATO: "+user.getUsername());
sessione.setAttribute("utente", user);
String salutoUtente = "Benvenuto "+user.getNome();
sessione.setAttribute("messaggio", salutoUtente);
}
}
else
System.out.println("FILTRO LOGIN----->USER FOUND: "+user.getUsername());
sc.log(httpRequest.getRemoteHost()+" cerca di accedere alla risorsa: "+httpRequest.getRequestURL()+
" il "+TimeUtility.ottieniDataOra()+". "+filterConfig.getFilterName());
System.out.println("FILTRO FILE DI LOG----> LOGGING OCCURED IN LOG FILE: "
+httpRequest.getRequestURL()+" il "+TimeUtility.ottieniDataOra()+". "+filterConfig.getFilterName());
chain.doFilter(request, response);
}
public void destroy()
{
filterConfig = null;
}
}

Simply user = sessione == null ? null : (Utente) sessione.getAttribute("utente"); and after else { just: sessione = httpRequest.getSession(true); Prevents holding sessions for non-users. – Joop Eggen yesterday
HttpSession sessione = httpRequest.getSession(false);
if (sessione == null) {
System.out.println("FILTRO LOGIN----->USER NOT FOUND IN SESSION!");
– Salvatore Servodio 44 mins ago
Then I checked the cookies. If I find the cookie i need i simply create a new session and put the USER info in the session , otherwise i simply redirect to the login page

Related

Why am I getting nullpointer error?

To retrieve cookies from browsert, I wrote a simple function dispcookies(). When I compile, I got nullpointerException and then I just copied that code from dispcookies() and put in processRequest() that time I didn't get the error why it happens.
HttpServletRequest request;
HttpServletResponse response;
PrintWriter out=null;
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try {
out = response.getWriter();
String name=request.getParameter("name");
String phone=request.getParameter("phone");
Cookie cname=new Cookie("name",name);
Cookie cphone=new Cookie("phone",phone);
response.addCookie(cname);
response.addCookie(cphone);
out.println("here ok");
dispcookies ();
}
catch(Exception E)
{
out.println(E);
}
}
void dispcookies () throws IOException
{
Cookie[] cookies;
Cookie cookie;
cookies=request.getCookies();
if(cookies!=null)
{
for(int i=0;i<cookies.length;i++)
{
cookie=cookies[i];
out.println("cookie name"+cookie.getName());
out.println("cookie name"+cookie.getValue());
}
}
else
{
out.println("no foumd cooke ");
}
}
At void dispcookies () you are trying to access to a property of the attribute request. WARNING: This request IS NOT THE SAME that the input parameter of the processRequest method. dispcookies doesn't have visibility over these input parameter, only can see the attribute HttpServletRequest defined at the beginning of the class and this attribute has not been initialized so every access to it will cause a null pointer exception.
If you want to access to the processRequest' request input parameter you must change the dispcookies signature to accept this object as input parameter and use it.
By the way:
cookies=request.getCookies();
if(cookies!=null) {
for(int i=0;i ...
could cause a null pointer exception because Cookies[] can be not null but empty and you are accessing to its zero position without checking the emptyness of the array.

Cannot call sendRedirect() after downloading PDF

I saw many questions like the one I am asking, but they are not exactly about what I am looking for.
I am using Command pattern, and want to create PDF-file and download it. Creating is perfect, but when I want to download it, it's starts downloading and throws an exception.
java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed
org.apache.jasper.JasperException: java.lang.IllegalStateException: getOutputStream() has already been called for this response
java.lang.IllegalStateException: getOutputStream() has already been called for this response
Here is my code from Command Pattern
#Override
public String execute(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException, AppException {
String fontPath = request.getServletContext().getRealPath(AppConstants.FONT_PATH);
DBManager db = DBManager.getInstance();
String ticketCode = request.getParameter("ticketCode");
String place = request.getParameter("place");
int amountTickets = Integer.valueOf(place);
String flightName = Encoding.encoding(request.getParameter("flightName"));
User user = (User) request.getSession().getAttribute("client");
String locale = (String) request.getServletContext().getAttribute("currentLocale");
db.updateFlightTickets(flightName, --amountTickets);
///////create pdf document and represent it to the byte array
ByteArrayOutputStream baos =ReportCreator.createReport(locale, fontPath, ticketCode, place, user,
db.getFlightByName(flightName));
response.setContentType("application/pdf");
response.setContentLength(baos.size());
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Disposition","attachment; filename=\"Ticket\"");
OutputStream os = response.getOutputStream();
baos.writeTo(os);
os.flush();
os.close();
return Path.SUCCESS;
}
Here is my "success page", sorry but can not add more, not enough reputation
<fmt:message key="success_jsp.label.success" />
And here is my servlet code
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
process(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
process(request, response);
}
private void process(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
String commandName = request.getParameter("command");
Command command = CommandContainer.get(commandName);
String forward = "";
try {
forward = command.execute(request, response);
} catch (AppException ex) {
request.setAttribute("errorMessage", ex.getMessage());
}
if (forward.equals(Path.SUCCESS)) {
response.sendRedirect(forward);
} else {
request.getRequestDispatcher(forward).forward(request, response);
}
}
Part of code in JSP, where click is calling the servlet
<td><button><fmt:message key="welcome_jsp.submit.buy_ticket" /></button></td>
How can i avoid it?
The exception says you are trying to working with the request/response once you redirect it or viceversa, and it's not valid.
Once you redirect a request, you cannot do anything else with the request/response, so getting the output stream and writing something to it is completely insane.
It's true about vice-versa situation, writing something and then redirect it will cause the browser will ignore the response data, or exception on server as I'm guessing you got.(but it depends on container)
So you either do not redirect the browser, or provide the pdf file with the target servlet/cgi where you are trying to redirect.
=================
And your current situation/problem:
Server sets the content-length, content-type,... and starts to write down some stream to the browser, since you haven't set any status, container will set default 200 OK which indicates there is some right response for the request.
Then browser will get some data(the pdf file) as 200 OK data(and consider it done), now how would you redirect the user once the response is almost done?!!?!!?!
I still do not understand why do you like to redirect a request when it's almost closed? you like to redirect the user after download complete? you cannot.

Twitter OAuth "Failed to validate signature and token."

I am having trouble getting a response from the Twitter API. I am using scribe 1.3.5 here. When TwitterLoginServlet is called from one page it successfully redirects me to twitter and allows me to login. However, on the callback, TwitterCallbackServlet receives the following information in the oAuthResponse.
code - 401
message - Unauthorized
body - Failed to validate oauth signature and token
I am new to using both servlets and oauth so it is completely possible I am making some silly mistake in the following code. I believe this is all that is needed to find a solution to the problem but if you need additional information I will be checking this post vigilantly.
Thanks!
public class TwitterServlet extends HttpServlet {
private static final String SESSION_NAME_REQUEST_TOKN = "twitter.requestToken";
protected Token getRequestToken(HttpServletRequest req) {
HttpSession session = req.getSession();
try {
return (Token) session.getAttribute(SESSION_NAME_REQUEST_TOKN);
}
finally {
session.removeAttribute(SESSION_NAME_REQUEST_TOKN);
}
}
protected void setRequestToken(HttpServletRequest req, Token token) {
HttpSession session = req.getSession();
session.setAttribute(SESSION_NAME_REQUEST_TOKN, token);
}
protected OAuthRequest createRequest() {
OAuthRequest request = new OAuthRequest(Verb.GET, "https://api.twitter.com/oauth/request_token");
return request;
}
}
public class TwitterLoginServlet extends TwitterServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String callback = "http://" + request.getServerName() + ":" + request.getServerPort() + "/******/TwitterCallbackServlet";
OAuthService service = new ServiceBuilder().provider(TwitterApi.SSL.class)
.apiKey("******")
.apiSecret("******")
.callback(callback)
.build();
Token requestToken = service.getRequestToken();
setRequestToken(request, requestToken);
response.sendRedirect(service.getAuthorizationUrl(requestToken));
return;
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
public class TwitterCallbackServlet extends TwitterServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
OAuthService service = new ServiceBuilder().provider(TwitterApi.SSL.class)
.apiKey("******")
.apiSecret("******")
.build();
Token requestToken = getRequestToken(request);
// TODO: Check if the requestToken matches the token of this request.
String verifier = request.getParameter(OAuthConstants.VERIFIER);
Token accessToken = service.getAccessToken(requestToken, new Verifier(verifier));
OAuthRequest oAuthRequest = createRequest();
service.signRequest(accessToken, oAuthRequest);
Response oAuthResponse = oAuthRequest.send();
String body = oAuthResponse.getBody();
response.sendRedirect("/******/accountSettings.xhtml");
}
Why are you hitting the requestToken endpoint again after getting the access token? Try accessing a different resource, for example:
"https://api.twitter.com/1.1/account/verify_credentials.json";
Note that you can run the TwitterExample just to check that stuff is working fine.

Login page doesn't render stylesheet after filter

'm working on a JSF 2 project. I have defined my login.xhtml page as the entry page in web.xml
<welcome-file-list>
<welcome-file>login.xhtml</welcome-file>
</welcome-file-list>
And I also have a filter to check if user is logged in
#WebFilter(filterName = "loginCheckFilter", urlPatterns={"/*"})
public class LoginCheckFilter implements Filter
{
#Inject
private LoginStatus loginStatus;
public void do Filter(...)
{
try{
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String path = req.getRequestURI();
if(StringUtils.isNotBlank(path)
&& StringUtils.contains(path, ".xhtml")
&& !StringUtils.endsWith(path, "login.xhtml"))
{
if(loginStatus == null
|| !loginStatus.isLoggedIn())
{
res.sendRedirect(req.getContextPath() + "/login.xhtml");
}
else
{
chain.doFilter(request, response);
}
}
else
{
chain.doFilter(request, response);
}
}catch (Exception ex)
{
log.error(ex);
}
}
.... ....
}
My css files were referenced in following style:
<link href="css/styles.css" rel="stylesheet" type="text/css"/>
Everything works well until I change the css reference style to the JSF 2 Resource handler (http://www.mkyong.com/jsf2/resources-library-in-jsf-2-0/). I have copied all my css files under a resources folder and gave library name and version number. So now I reference the css as following:
<h:outputStylesheet library="default" name="css/styles.css"/>
After the change, the login.xhtml does not render the stylesheet any more. I have a welcome.xhtml page right after login.xhtml page, which has almost identical structure except for the core content, but this page render perfectly fine. I have refreshed the login.xhtml still it does not render. But once I logged in, advance to next page, then come back to login.xhtml, then refresh, the style will get rendered. Also, if I take off the loginCheckFilter, the login.xhtml will rendered the stylesheet. So if anybody ran into the similar situation and know how to resolve it? Thanks!
urlPatterns={"/*"}
Your filter is also blocking requests to JSF resources.
You need to rewrite your filter in such way that it allows JSF resource requests.
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String loginURL = request.getContextPath() + "/login.xhtml";
boolean loggedIn = loginStatus != null && loginStatus.isLoggedIn();
boolean loginRequest = request.getRequestURI().startsWith(loginURL);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + "/faces" + ResourceHandler.RESOURCE_IDENTIFIER);
if (loggedIn || loginRequest || resourceRequest)) {
if (!resourceRequest) { // Prevent restricted pages from being cached.
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(request, response);
} else {
response.sendRedirect(loginURL);
}
}

Play Framework and custom http headers. How to?

I need to send custom HTTP header with login information to my play application (play 1.2.5). That custom header is added by filter.
Problem is that play always throws NullPointerException when I attempt to read:
String loggedUser = request.headers.get("loggeduser").value();
I have also a servlet for testing, where following prints vale from header correctly.
out.println(request.getHeader("loggeduser"));
Am I missing something in play?
Thanks
EDIT: This is my filter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
CustomHeaderWrapper wrapper = new CustomHeaderWrapper((HttpServletRequest) request);
String username = ((HttpServletRequest) request).getRemoteUser();
wrapper.addHeader("loggeduser", username);
chain.doFilter(wrapper, response);
}
And CustomHeaderWrapper:
private Map<String, String> customHeaderMap = null;
public CustomHeaderWrapper(HttpServletRequest request) {
super(request);
customHeaderMap = new HashMap<String, String>();
}
#Override
public String getHeader(String name) {
String header = super.getHeader(name);
return (header != null) ? header : this.getParameter(name);
}
#Override
public Enumeration getHeaderNames() {
List<String> names = Collections.list(super.getHeaderNames());
names.addAll(Collections.list(super.getParameterNames()));
return Collections.enumeration(names);
}
#Override
public String getParameter(String name) {
String paramValue = super.getParameter(name); // query Strings
if (paramValue == null) {
paramValue = customHeaderMap.get(name);
}
return paramValue;
}
public void addHeader(String headerName, String headerValue) {
customHeaderMap.put(headerName, headerValue);
}
I created a little test project, and used the line of code from your question. It works perfectly. I used the Dev HTTP Client plugin for Chrome to set the header.
Remember that all headers are converted to lowercase, before they are added to the request.headers hashmap. So if you placed "loggedUser" inside request.headers.get(), it would never work.

Resources