I want to use JS to load another JS file from a server but i want to do it conditionally example if the userId sent by the request is in my database send back the file.
So i thought of creating an interceptor.
Is there a better way to do it because an interceptor would be an overkill?
<mvc:interceptors>
<mvc:interceptor>
<bean class="com.mycomp.webservice.UserInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
public class UserInterceptor extends HandlerInterceptorAdapter {
#Autowired
UserService userService;
#Override
#Transactional
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
if(!userService.userPresent(request)){
return false;
}
else{
return true;
}
}
Edit: So i figured out that the question isn't that clear. the file i want to upload is part of the static resources so i don' want to just load it to the client, i want to cache it as well.
So i leave you with a link.
Edit 2: So this is what i ended up doing. under my mvc-resources config i created an interceptor to handle request for protected static resources.
<mvc:resources mapping="/static/**" location="/static/" />
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/static/protected/**" />
<bean class="com.mycompany.interceptor.ProtectedResourcesInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
public class ProtectedResourcesInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if("your condition is true") {
System.out.println("Access Granted to protected resources");
return true;
}
return false;
}
}
The interceptor will handle requests to /static/protected and if conditions are right it will serve it. If anyone has a cleaner solution please share it.
Related
This question already has answers here:
Disable browser authentication dialog in spring security
(3 answers)
Closed 1 year ago.
I'm creating a simple app with a Sign-In site.
I used HTTP basic type of authorization, but the problem is I don't know how to disable the pop-up window which is showing every time when I pass wrong credentials or in case of writing secured endpoint site before authentication.
The frontend is written in pure JS, launched without any template engine. Just js + html files in static dir.
The authentication page uses the Fetch Api to send headers with credentials
Does someone knows how to disable this window, shown below:
Here is my Security config class:
#Configuration
#EnableWebSecurity
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Resource
private UserDetailsService userDetailsService;
#Autowired
private CustomLogoutHandler logoutHandler;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.POST, "/demo/users/save").permitAll()
.antMatchers(HttpMethod.POST, "/demo/users/**").permitAll()
.antMatchers(HttpMethod.POST, "/users/*/save").permitAll()
.antMatchers(HttpMethod.DELETE, "/users/**").permitAll()
.antMatchers(HttpMethod.POST, "/users/*/verify").permitAll()
.antMatchers(HttpMethod.GET,"/users/**").permitAll()
.antMatchers(HttpMethod.PUT,"/users/**").permitAll()
.antMatchers("/css/**", "/js/**", "/img/**").permitAll()
.antMatchers("/signup-page.html").permitAll()
.antMatchers("/landing-page.html").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.disable()
.logout()
.logoutUrl("/logout")
.addLogoutHandler(logoutHandler)
.logoutSuccessUrl("/landing-page.html")
.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK))
.permitAll()
.and()
.httpBasic();
}
#Bean
public DaoAuthenticationProvider authProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
I couldn't find the answer before, every response I found consisted of "disable httpBasic" and that wasn't a satisfying solution.
Here is a Topic :
Spring Boot security shows Http-Basic-Auth popup after failed login
and these lines solved my problem:
httpBasic()
.authenticationEntryPoint(new AuthenticationEntryPoint(){ //<< implementing this interface
#Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
//>>> response.addHeader("WWW-Authenticate", "Basic realm=\"" + realmName + "\""); <<< (((REMOVED)))
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
}
});
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 currently trying to develop a simple angular js application.
I am trying to post data from client to web api.
However, I am getting 404 error when I fire post request from angular app.
Below is my post request,
$http.post('/api/LoadApi/', jsonData).then(function (result) {
console.log(result.data);
})
.catch(function (error) {
});
where jsonData is a valid json data.
My web api code is this,
public class LoadApiController : ApiController
{
[HttpPost]
public HttpResponseMessage LoadData(object dataToLoad)
{
var response = Request.CreateResponse(HttpStatusCode.Created);
return response;
}
}
My web api route config is this,
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{dataToLoad}"
);
However, when I run the code, it throws an error
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /api/LoadApi/
Can anyone point what is the problem with the above code?
It says there is some problem with url. The url generated is http://localhost:14154/api/LoadApi/ which looks correct.
The issue is with your route definition and how you are trying to send data to your controller method. I would recommend using attribute based routing. In your Web API controller do this:
[RoutePrefix("api/LoadApi")]
public class LoadApiController : ApiController
{
[HttpPost]
[Route("loadData")]
public HttpResponseMessage LoadData(object dataToLoad)
{
var response = Request.CreateResponse(HttpStatusCode.Created);
return response;
}
}
Change the Application_Start() method in Global.asax.cs to this:
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
Make sure WebApiConfig.cs in App_Start has a Register() method like this:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
}
And finally change your $http.post call to this:
$http.post('/api/LoadApi/loadData', jsonData).then([...]);
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 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.