I have some url secured with spring (configured through xml). It works. However when I try to hit that endpoint with an ajax request I get a 302 (found) response. This redirects my ajax call to the login page (so I GET the html). However I'd like to get a 401 (unauthorized) response with the url of the login page available to the client application, so I can redirect the user there with javascript. This question seems to be the closest to what I want, but there's no example and it suggests changing the controller again. Is there no configuration in spring-security that will give me a 401 and a url (or some other sensible error message and the url of the login page)?
You can extend LoginUrlAuthenticationEntryPoint. Here is my one:
package hu.progos.springutils;
// imports omitted
public class AjaxAwareLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException, ServletException {
if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
} else {
super.commence(request, response, authException);
}
}
}
Then configure spring to use your implementation:
<beans:bean id="authEntryPoint" class="hu.progos.springutils.AjaxAwareLoginUrlAuthenticationEntryPoint" scope="singleton>
<beans:property name="loginFormUrl" value="/login.html" />
</beans:bean>
<http entry-point-ref="authEntryPoint">
<!-- your settings here -->
</http>
There are a million ways to do this of course. But the short solution to your problem is this configuration snippet:
<bean id="customAuthEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/your-custom-login" />
</bean>
I also take a step further and turn off the security auto-config so I can map the above entry point like so:
<security:http auto-config="false" entry-point-ref="customAuthEntryPoint">
...
...
</security:http>
I also override a bunch of spring security classes to get the security model to do exactly what I want. It's a slippery slope, but it's nice having the control once it works the way you want it to.
Related
I need to implement a requirement, where I need to deliver javascript code securely. My Idea is,
I will make the path as /something.js and in the controller, I will check the authentication, if not authenticate I will deliver console.error("Auth Failed").
How I can achieve the above scenario.
this is the simplest way using common request handler. works 100 %
#GetMapping(value = "/hello.js")
public void resources( HttpServletRequest httpRequest,
HttpServletResponse httpResponse) throws Exception {
//Authentication goes here or using handler interceptor
httpResponse.setContentType("text/javascript");
httpResponse.setHeader("MIME-type", "text/javascript");
httpResponse.getWriter().write(" function alertMan(msg) { \n alert(\"message:\"+msg); \n } ");
}
I am trying to make a post request with jquery to a spring rest controller I have setup. This works perfectly fine with the $.get request, however the post request is giving me a 403 error in the console. Is there any better way to handle this, or get it working at all?
$("#testBtn").click(() => {
$.post("/test").done((data) => {
console.log(data);
})
});
My Controller:
#RestController
public class LiveValidationController {
#PostMapping("/test")
public String checkEmail() {
return "hello";
}
}
403 status = forbidden.
You receive this error because you have CSRF protection enabled.
Solution 1: send csrf token in your post from js
Solution 2: disable csrf in the spring security configuration.
The csrf protection is usually enabled by default if you have a dependency to spring-security module
I have two different java projects and I need them to interact with each other. The first one named RESTfulWebServer is a dynamic web project which contains the basic HTTP GET PUT POST requests in a java class named UserServices. It just prints one line statements right now on console(output window in netbeans), so nothing complex.
The other project named ClientProject is also a dynamic web project which contains a simple jsp page containing javascript code. It is supposed to make call to the RESTfulWebServer project and print the output line on console(output window in netbeans) the same way the RESTfulWebServer project does when a simple GET request is made to it.
This is the part where the problem arises. When I run the ClientProject the javascript function is being called properly (as I checked by printing an alert message), but it is not making the DELETE HTTP request to the RESTfulWebServer as it is supposed to.
Both the codes are attached below:
RESTfulWebServer (UserServices.java)
package com.service.user;
import javax.ws.rs.*;
#Path("/user/service")
public class UserServices {
#GET
public void getUser()
{
System.out.println("Inside get user method");
}
#POST
public void updateUser()
{
System.out.println("Inside update user method");
}
#DELETE
public void deleteUser()
{
System.out.println("Inside DELETE user method");
}
}
ClientProject (clientfile.jsp)
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Update User</title>
<script>
function loadResponse()
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState === 4 && xmlhttp.status === 200)
{
document.getElementById("myDiv").innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("DELETE","http://localhost:8080/app/user/service",true);
xmlhttp.send();
}
</script>
</head>
<body>
<div id="myDiv">The response text would come here</div>
<button type ="button" onclick="loadResponse()">submit</button>
</body>
</html>
The clientfile is supposed to print on console "Inside DELETE user method" but nothing is showed on console after "Build successful" message
What am I doing wrong? Also I am making use of TomCat server and doing this in NetBeans and I have to work on this IDE solely for some reason (kindly do not suggest to move to any other IDE and check it) if there is any mistake in my code or anything else pleaseee mention it?
First of all starting with requesting URL http://localhost:8080/app/user/service
when it falls in class level annotation - there are three methods so which one to pick so, needed to provide method level annotations as well for better approach.
#Path("/user/service")
public class UserServices {
#Path("/getUser")
#GET
public void getUser() { System.out.println("Inside GET method"); }
#Path("/updateUser")
#POST
public void updateUser() { System.out.println("Inside UPDATE method"); }
#Path("/deleteUser")
#DELETE
public void deleteUser() { System.out.println("Inside DELETE method"); }
}
Now coming towards something important which is necessary to make project(RestWebServer) accept requests from another project(Client Projects/app) which is hosted on separate domain, i.e. CORS (Cross Origin Resource Sharing)
CORS, in a nutshell, is a security check implemented like when an application requests for resources from or make server calls to another domain, these requests get blocked by browsers. Moreover you are using XMLHttpRequest which forces same-origin policy i.e. request should generate from same domain where resources are residing so in order to make requests allow cross domain accessing we implement CORS Filter logic on server side to allow methods (P,G,P,D) to get executed.
So add a class like this in your WebService Project in package where UserServices class is:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class CORSFilter implements Filter {
public CORSFilter() { }
public void init(FilterConfig fConfig) throws ServletException { }
public void destroy() { }
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
((HttpServletResponse)response).addHeader("Access-Control-Allow-Origin", "*");
((HttpServletResponse)response).addHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
chain.doFilter(request, response);
}
}
Now time to use this Filter in web.xml
<web-app ....>
<filter>
<filter-name>CORSFilter</filter-name>
<filter-class><package name -must be complete>.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
clientFile.jsp
Now call method like this from view page with just method annotation added
xmlhttp.open('DELETE','http://localhost:8080/app/user/service/deleteUser',true);
Last thing you will have to make two server instances of Tomcat to deploy, name them Service and Client Server respectively for your convenience while making them. Let the Service one have all default config but you will have to change all three Port number for Client Server to avoid binding error. For this simply double click on server (Client) see Ports heading and change ports.
All done, it should run now, tested as well. Hope this will help you and other thread readers as well.
I've got a requirement where we need to redirect to a page for JSF 1.2 Ajax call. In our case, we need to redirect to session expired page when the ajax call get fired after the session got expired. We are implementing the session expiry check in a filter and the invocation of httpservletresponse.sendRedirect is redirecting correctly to the session expired page as expected, but the url is not getting changed which is the issue now.
Any hints/soultion either at the client/server side is highly appreciated.
~Ragesh
Finally I managed to find a solution for the above problem.
In the filter, I set the response header "Location" and another custom header which I'll use in the client side to filter the response.
Filter code:
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
httpServletResponse.setHeader("x-timeout-status", "true");
httpServletResponse.setHeader("Location", httpServletResponse
.encodeRedirectURL(sessionexpiryurl));
Richfaces have got a javascript file with various callbacks required during the AJAX call invocation which is packed inside the Richfaces libraries. There is one callback function called "processResponse" which will get invoked upon receiving response for all AJAX call initiated by JSF Ajax components . I've made use of this to handle the redirection functionality.
JS code:
var originalAjaxProcessResponse = A4J.AJAX.processResponse;
A4J.AJAX.processResponse = function(req) {
if (req.getResponseHeader('x-timeout-Status') != undefined && req.getResponseHeader('x-timeout-status') == 'true') {
window.location.href = req.getResponseHeader('Location');
} else {
originalAjaxProcessResponse(req);
}
}
Here we are overriding the method to handle our specific case and delegate the rest of the ajax call response handling to the in-built processing provided by richfaces.
Please let me know if you see any limitation to this solution or have a better solution to this problem
~Ragesh
I was wondering if there is a way to get the URL of the returned resource after a AJAX call in JavaScript?
I want to use this with a form, which is in "mysite.com/users/add.html". This is a Spring MVC controller. If the validation of the form fails the controller will return the "users/add" view, but if the validation is OK it will do a redirect to "mysite.com/users/index.html", using
return new ModelAndView(new RedirectView("/users/index.html"));
Is there a way in JavaScript to find the URL of the returned page?
Thanks,
Stian
Solved this by setting the response header "Location" in a Java Filter.
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String path = httpRequest.getRequestURI();
httpResponse.setHeader("Location", path);
In JavaScript I could then use
XMLHttpRequest.getResponseHeader("Location")
Hopefully this won't cause any unforeseen problems. :P
If anyone else have an easier solution though I'd like to see it.