I'm building a Spring MVC application with Spring Security and Bootstrap in my HTML files (thymeleaf templates). The Spring Security part is based on the Spring Guide for Spring Security and combined with a Spring Boot application server.
After enabling Spring Security the bootstrap css file won't load with the error message:
Refused to execute script from 'http://localhost:8080/js/bootstrap.min.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
The error message above comes from the chrome developer console.
What I've tried:
Disabling the Spring Security
=> bootstrap css works again, but I need the security
Searching on the spring forums, but theres a looped link without a solution
Adding a resources handler, but I can't see that the handler is invoked nor the error disappears
Adding the resources path to the permit call
My dir structure:
/main
|-> /java
| BootStart.java
|-> /security
|SecurityConfiguration.java
|-> /resources
|-> /static
|-> /css /** bootstrap location */
|-> /js
|-> /fonts
|-> /templates
| /user
| sample.html
BootStart.java is the java file that gets picked up by Spring Boot.
BootStart.java:
#EnableAutoConfiguration
#ComponentScan
public class BootStart {
public static void main(String[] args) {
SpringApplication.run(BootStart.class, args);
}
}
SecurityConfiguration.java:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
http
.authorizeRequests()
.antMatchers("/", "/resources/static/**").permitAll()
.anyRequest().authenticated();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
Sample.html:
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" th:href="#{/css/bootstrap.css}" href="../../css/bootstrap.min.css"/>
<link rel="stylesheet" th:href="#{/css/bootstrap-theme.css}" href="../../css/bootstrap-theme.min.css"/>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<div class="alert alert-danger" role="alert">!Basic template!</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
</body>
</html>
Currently I'm using the following dependencies in my pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
How must I configure Spring Security that I can load css/ js files from my /static resources directory?
Please check this answer by other with similar question.
If you place js files in /js/ dir, there should not that kind of MIME error.
And, for javascript files, it is better to disable security for them:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/the_js_path/**");
}
I had the same error too with the same folder structure, it was on the css file.
All I did is added /css/** in antMatcher() as below:
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers("/css/**").permitAll() //Adding this line solved it
.anyRequest().fullyAuthenticated()
.and()
.formLogin()
.loginPage("/login").permitAll()
.loginProcessingUrl("/sign-in")
.defaultSuccessUrl("/home")
.failureUrl("/error")
.and()
.logout()
.logoutSuccessUrl("/logout")
.permitAll()
.and()
.csrf().disable();
}
In your case just add /js/** in the antMatcher() and then use permitAll()
I used this to resolved my problem, you may try this
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
Hope it help.
I had this problem, and struggled for a while. I had created a route which should match every "unmatched" route, and send index.html.
#Controller
public class DefaultPageController {
#Autowired
private LogService logService;
#GetMapping("/*")
public String defaultPage(Model model){
logService.saveLog(Log.LogType.INFO, null, "Default route");
return "index";
}
}
The problem was, that it overrode the route /file.js, and didn't send the static files, but always index.html.
So the solution was only to customize the route.
I had the same error after adding a new method to a controller.
I forgot to provide a value for the #GetMapping annotation and the #Controller itself was not bound to any URL. Wierdly enough adding #GetMapping("/foo") to my method solved the problem. I still haven't figured out why that happened but I'm planning to find out.
when we use "permitall()" or anyrequest() then it enable Mime check so i specify all url listing which use to be accecs.
I removed any comments from the beginning of the css file and it works.
Checklists to import static resources file into Spring MVC with Security Web Configuration:
Permit pattern matcher in configure method which extends from WebSecurityConfigurerAdapter
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/loginPage").loginProcessingUrl("/authenticateUser")
.permitAll();
}
Mapping resources location in configuration by implements WebMvcConfigurer
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
Create the resources folder and subfolders to store the static files.
/src/main/webapp/
|-> resources
| -> css
| -> style.css
Add resources into the JSP file
<link rel="stylesheet" type="text/css" href="css/style.css">
Remember that in the controller file always specify the path even though the home page
#RequestMapping("/")
Related
I tried all the suggestions from here but i could not make it work
spring boot security static resources
I have to specify that the image i am trying to add is on the log in page.
I am using maven to create a spring boot webapp with security and thymeleaf.
It seems that all my static resources load fine(css/jss)but the images do not.When i check the developer tools in chrome i get a 404 error for that said image in the console.no matter what path i am using i am geting the same error.I have permited access to all the static content here
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers(HttpMethod.GET,"/resources/**" ,"/js/**", "/css/**", "/images/**" ,"/fonts/**", "/scss/**", "/index", "/", "/login").permitAll()
.and()
.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.defaultSuccessUrl("/home", true)
.and()
.logout()
.logoutSuccessUrl("/")
.logoutUrl("/signout");
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**"); // #3
}}
this is how i access it in thymeleaf
<div class="col-lg-2 ml-auto" data-aos="fade-up" data-aos-delay="100">
<figure class="img-absolute">
<img th:src="#{/images/car.jpeg}" alt="Image" class="img-fluid">
</figure>
</div>
this is my folder structure
src->main->resources->static->images->car.jpeg
and this is the error i get in dev tools
GET http://localhost:8080/images/car.jpeg 404
any help would be greatly appreciated.
Use this approach to get the static images and other resources to load on your html page -
1.) Correct your folder structure for images, It should be -
your_project_name -> src -> main -> resources -> static -> assets -> img --> your images
NOTE - Add your other static files and folders inside assets folder.
2.) And your Security config class -
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// your code
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/assets/**");
}
}
3.) Use correct url on your html page to access the images -
//your code
<img th:src="#{/assets/img/car.jpeg}" alt="Image" class="img-fluid">
I know how to disable swagger for production - i only need to add annotation #Profile("!prod") in configuration class:
#Configuration
#EnableSwagger2
#RequiredArgsConstructor
#Profile("!prod")
public class SwaggerConfig {
result of adding annotation
But the result is, that the swagger-ui.html still is available in browser, only its empty. I wonder is there solution to disable it fully, so the page will not load?
this could be simply done with spring-security by blocking the url for the production environment. Please try :
Add dependency (if you are using spring-boot) to pom.xml :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Add configuration file :
#Configuration
#Profile("prod")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**/swagger-ui.html").denyAll();
}
}
It will send 403 forbidden status.
Okey #zpavel its good solution, thank you. I just already had such spring security configuration, and when i added yours, i got error "#Order on WebSecurityConfigurers must be unique.", so i added to one class #Order(1), and to the other one #Order(2). Unfortunately the .antMatchers("/**/swagger-ui.html").denyAll(); denied all request even those who were not swagger calls, i don't know why.
Hovewer i modified Your solution and it worked for me:
#Value("${spring.profiles.active}")
private String activeProfile;
#Override
public void configure(HttpSecurity http) throws Exception {
if(activeProfile.equals("prod")){
http.authorizeRequests()
.antMatchers("/something").permitAll()
.antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/**", "/swagger-ui.html", "/webjars/**").denyAll()
.antMatchers("/something").permitAll()
.anyRequest().authenticated();
} else {
http.authorizeRequests()
.antMatchers("/something").permitAll()
.antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/**", "/swagger-ui.html", "/webjars/**").permitAll()
.antMatchers("/something").permitAll()
.antMatchers("/something").permitAll()
.anyRequest().authenticated();
}
}
I have a quick issue which am not really sure how to sort this out yet.
The issue is that, I'm using Thymeleaf, and was working perfectly fine until I've introduced the Springboot security. Since then, the styling isn't working at all. Looks like the static folder isn't seen for some reason. I've tried several structures to make it work but still no luck. I've tried to include in resource folder static folder, then resource folder (again) with no luck. I've also tried to rename the static into public, still no luck. I've noticed that if you include the URL somewhere on the web it works but if you include the URL somewhere on your local machine doesn't work. So I'm 100% sure there is a problem with the structure of the folders or the Spring configuration.
Any help, would be really much appreciated.
Spring security configuration class:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin()
.loginPage("/login")
.usernameParameter("username")
.passwordParameter("password")
.failureUrl("/login?error")
.defaultSuccessUrl("/default")
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/", "/static/**").permitAll()
.antMatchers("/createUser").hasRole("ADMIN")
.anyRequest().authenticated();
}
}
WebConfig class:
#Configuration
#EnableWebMvc
public class WebAppConfig {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
I am using spring boot and angular in front end. Sometimes I want to redirect directly from a service. We are using only .html, .css and script files (no .jsp).
This is return "static/pages/savepassword.html"; how I tried to redirect to savepassword
So 1st question how do I redirect properly in this case?
Next, Spring doesn't find my html files. I have this structure
I read that spring should find all static files in "static" automatically, but it doesn't. So I tried to configure my ViewControllerRegistry and RessourceControllerRegistry
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
// registry.addResourceHandler("/stylesheets/**").addResourceLocations("/stylesheets/");
// registry.addResourceHandler("/scripts/**").addResourceLocations("/scripts/");
// registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/savePassword").setViewName("static/pages/savePassword.html");
registry.addViewController("/login").setViewName("static/pages/login.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
When I call "static/pages/login.html" directly, it works. When i want to call "/login" it says 404.
2nd question: What do I need to configure and what not?
UPDATE-1: Spring Security
http
.authorizeRequests().antMatchers("/login", "/logout", "/user/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.accessDeniedHandler(new CustomAccessDeniedHandler())
.authenticationEntryPoint(new CustomAuthenticationEntryPoint())
.and()
.requiresChannel()
.anyRequest().requiresSecure()
.and()
.csrf()
.disable()
//.csrfTokenRepository(csrfTokenRepository())
.addFilterBefore(new MDCFilter(), ExceptionTranslationFilter.class)
// .addFilterBefore(new CorsFilter(),// ChannelProcessingFilter.class)
//.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
.formLogin()
.successHandler(new CustomSuccessAuthenticationHandler())
.failureHandler(new CustomFailureHandler())
.loginPage("/login").permitAll();
UPDATE-2
I updated my structure, but still have problems with redirecting from /login to the custom login.
UPDATE-3
I had a look at the 2nd comment by Bob Shields: https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot
I did the following:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/savepassword").setViewName("savepassword.html");
registry.addViewController("/login").setViewName("login.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
I set .html because otherwise /login would cause recursive problems. With this config, I can enter /login and /templates/login.html will be called (same for savepassword.html).
Now, I would like to know how to include my css/js in html:
<link rel="stylesheet" type="text/css" href="..resources/stylesheets/bootstrap.min.css" />
<script src="..resources/scripts/angular.min.js"></script>
<script src="..resources/scripts/login.js"></script>
This doesn't work...but I cann call my scripts directly with /scripts/login.js.
In my opinion it is better to put your *.HTML files in your resources folder with all the static CSS FONTS and so on like in the picture below. In webapp you can have a WEB-INF folder only.
I am using this kind of structure and I have no problems finding any classes css or htmls and I do not use extensions at the end in java ("static/pages/login.html" like yours). If I want to access html I go like "user/someHtml" if it is in folder user for ex.
I know this answer is not precisely the one you are looking for but it may help you in someway.
EDIT: Now for the :
#Override
public void addViewControllers(ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/savePassword").setViewName("static/pages/savePassword.html");
registry.addViewController("/login").setViewName("static/pages/login.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
Lets say you have a Controller:
#Controller
#RequestMapping("/myController")
public class MyController{
...
#RequestMapping(value = "/login")
public String login(Model model) {
// Your code ....
return "login"; //<- this is your login.html if it is directly in resource/templates folder
}
#RequestMapping(value = "/savePassword")
public String savePassword(Model model) {
// Your code ....
return "savePassword"; //<- this is your savePassword.html if it is directly in resource/templates folder
}
.....
}
Now your addViewController show look like this :
#Override
public void addViewControllers(ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/savePassword").setViewName("forward:/myController/savePassword");
registry.addViewController("/login").setViewName("forward:/myController/login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
You see in your addViewController you are trying to access a CONTROLLER not a HTML you will access your HTML through the CONTROLLER you access from the method addViewControllers.
UPDATE:
If you put your CSS into your static folder in resources like :
You can simply access them like this :
<link rel="stylesheet" th:href="#{/css/bootstrap-datetimepicker.min.css}" />
Hope this helps!
Ok, now I totally got it. I try to be specific as possible.
My final structure
1. Static Ressources
Spring has some default configuration where you can put your static ressources without configure it. You need to create those folders in src/main/resources
/META-INF/resources/
resources (yes, an additional resources folder in src/main/resources
static
public
Have a look here in Spring Doku. For an example, check the 2nd comment by Bob Shields:
After creating a bunch of "findme.txt" files, each of which had different "source-relative" path string inside, I found that the following locations can be fetched with "http://host/findme.txt" are:
src/main/resources/public/findme.txt
src/main/resources/static/findme.txt
src/main/resources/resources/findme.txt - (yes, resources^2!)
src/main/resources/findme.txt - not found!!
I placed my folder "scripts" and "stylesheets" in the static folder. When I want to include files from these folders in html, the source looks like src="scripts/file.js"because the files and folders in staticare found directly rooted to host/scripts/file.js
No ResourceHandlerRegistry was necessary for me!
2. View Controller
I wanted to root my login.html to /login, savepassword.html to /savepassword and my index.html to /. Here is what I did:
registry.addViewController("/savepassword").setViewName("savepassword.html");
registry.addViewController("/login").setViewName("login.html");
registry.addViewController("/").setViewName("loggedin/index.html");
I set *.html because otherwise I had a problem that spring didn't know to differ between /login and the login(.html).
As you can see I placed the index.html in a different folder called "loggedin". This folder is right in my public-folder (found by Spring, see 1.). Why do I do this? Have a look at 3.
3. Spring Security
.authorizeRequests().antMatchers("/stylesheets/**", "/scripts/**","/login", "/user/**").permitAll()
...omitted further configuration...
.loginPage("/login").permitAll();
First, I want that a user always has to be logged in before he can visit any other sites. So all ressources for loginpage must be available.
This piece of code makes every file in stylesheets and scripts accessible. Remember stylesheets and scripts-folder are placed in static. I had to set "/login" because of the custom loginpage.
Honestly I thought that the .loginPage("/login").permitAll();would grant access, but it doesn't. Without it Spring tries to access the "/login", but can't cause of no rights and then automatically redirects to login => ERR_TOO_MANDY_REDIRECTS.
"/user/**" is just for some of my services that every user can use.
As you can see, I don't give access to "loggedin"-folder, so that every visitor can enter files in "loggedin" only if he is loggedin ;)
4. Redirecting
I just marked my whole controller with #RequestController, which implements #ResponseBody. When I return a String like return "redirect:/savepassword";, Spring will set this as ResponseBody and it will be interpreted as String/Json(?).
I had to mark the controller as #Controller and set #ResponseBody to every service that must return json or sth. My service that shall redirect was only marked with #RequestMapping and method=RequestMethod.GET. Finally, I return a String like return "redirect:/savepassword"; This will make Spring redirect to /savepassword, which actually is placed in src/main/resources/public/savepassword.html.
Finally, it works and it was hard enough to find how spring serves the files. I hope it helps someoneelse :)
I work on angularjs application and I try to serve static resource (my front end) with Spring boot.
I used gulp to build project and I get this distribution structure:
here is the content of hash folder
my spring security config look like this:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(myEntryPoint());
http
.authorizeRequests()
.antMatchers("/__hash__/**").permitAll()
.antMatchers("/views/**").permitAll()
.antMatchers("/index.html").permitAll()
.antMatchers("/api/**").authenticated()
.antMatchers("/**").permitAll();
http // login configuration
.addFilterAfter(springSecurityFilter(), BasicAuthenticationFilter.class);
/*http
.authorizeRequests()
.anyRequest().authenticated();*/
http //logout configuration
.logout()
.logoutSuccessHandler(logoutHandler());
http.csrf().disable();
}
The config spring for serving static content:
#Configuration
public class MyContentConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/**")
.addResourceLocations("file:///" + "c:/front/") ;
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/index.html");
}
}
After authentication, I get the index.html page but without css style and without js.
And when I try to access to css using this url "https://localhost:9999/hash/styles.min.css" I get this error:
There was an unexpected error (type=Not Acceptable, status=406).
Could not find acceptable representation
You are loading livereload.js over http. If you are using https, all resource must be load over https.
so load livereload.js over https.
I resolved the problem. it's related to "spring-cloud-config-server". I just delete this config:
org.springframework.cloud
spring-cloud-config-server