CSS stylesheet doesn't work with Spring Security + Spring Boot + Thymeleaf - css

After much research, I haven't been able to find a solution. I have a project implemented with Spring Boot + Spring Security + Thymeleaf.
I have a REST API multi-module project and a web client built with Thymeleaf. My problem is that I can't seem to include my CSS stylesheet in my Thymeleaf page.
MvcConfig :
#Configuration
public class MvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.
addResourceHandler(
"/css/**",
"/img/**").
addResourceLocations(
"classpath:/resources/static/img",
"classpath:/resources/static/css");
}
My Html (Thymeleaf)
<!DOCTYPE HTML >
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head xmlns:th="http://www.thymeleaf.org">
<title>Bibliothèque d'OC</title>
<link rel="stylesheet" type="text/css" th:href="#{/static/css/style.css}">
<!-- CSS only -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<!-- JS, Popper.js, and jQuery -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
</head>
I've tried changing the value of the path set on the th:href attribute of the link tag (th:href="#{/static/css/style.css}"). And I've also tried adding an href attribute to the link tag; neither one helped. I can't find the solution.
Can someone suggest a solution?

TL;DR — Change th:href="#{/static/css/style.css}" to th:href="#{/css/style.css}".
The long-winded version
Thymeleaf expects projects to have a particular, default directory structure: src/main/resources/static. The path that you set for Thymeleaf's special th:href attribute must be relative to that expected directory structure.1
The snippets in your original question and your replies in the comments, suggest that your project is laid out like this…
…
└───src
└───main
│
└───resources
├───static
│ └───css
└───templates
If that is the case, then the relative path to your stylesheets that you need to give to Thymeleaf should be: th:href="#{/css/style.css}".
If that is not the case and your project's directory structure is something different than what I illustrate above then please share, in the comments of this answer, what exactly your directory structure is.
I noticed that you declare the Thymeleaf th namespace twice; once in the html tag, then again in the head tag. There should be only one namespace declaration.2 My advice is that you remove the one in the head tag.
Consider this from a 2013 blog post on spring.io…3
…Spring Boot will automatically add static web resources located within any of the following directories:
/META-INF/resources/
/resources/
/static/
/public/
…
According to that, not only is this part of your application's configuration unnecessary, I have a hunch that it could be the root cause of your problem…
…
registry.
addResourceHandler(
"/css/**",
"/img/**").
addResourceLocations(
"classpath:/resources/static/img",
"classpath:/resources/static/css");
…
I've implemented at least a dozen different Spring Boot applications that served static content. I've never once had to implement any configuration code like you are doing there.
My advice is — in addition to the th:href attribute and th namespace declaration suggestions — remove that unnecessary registry.addResourceHandler( … ) configuration.
1 Add CSS and JS to Thymeleaf — Amy DeGregorio
2 Using Thymeleaf — Official documentation
3 Serving Static Web Content with Spring Boot — Spring Blog

Related

Using DateRangePicker in a Blazor libary

When using the component the doc. (https://github.com/jdtcn/BlazorDateRangePicker) says that this
<script src="_content/BlazorDateRangePicker/clickAndPositionHandler.js"></script>
<link rel="stylesheet" href="_content/BlazorDateRangePicker/daterangepicker.min.css" />
needs to be added to the app. in the head section.
Now I am using the BlazorDateRangePicker in a Razor component library - MyLibrary.
To use that library in my app. I need to add those to lines to my app referencing them in my library
<script src="_content/MyLibrary/BlazorDateRangePicker/clickAndPositionHandler.js"></script>
<link rel="stylesheet" href="_content/MyLibrary/BlazorDateRangePicker/daterangepicker.min.css" />
this does not work - I get 404 when loading the files. I have also tried
_content/MyLibrary/_content/BlazorDateRangePicker
and all other possible combinations.
How is this done ?
I think you're getting confused with how Blazor references embedded resources.
The BlazorDateRangePicker library's resources would be referenced as per the instructions, e.g.
<script src="_content/BlazorDateRangePicker/clickAndPositionHandler.js"></script>
<link rel="stylesheet" href="_content/BlazorDateRangePicker/daterangepicker.min.css" />
You're importing your own library (MyLibrary) that references this package, but the reference path doesn't change - it's still the _content/BlazorDateRangePicker/.. prefix.

Refused to apply style because its MIME type ('application/json') is not a supported

I want to use the fullcalendar library, using gulp and yarn this is the generated link tag:
But I'm getting this error in the console :
Refused to apply style from
'http://localhost/bower_components/fullcalendar/dist/fullcalendar.css'
because its MIME type ('application/json') is not a supported
stylesheet MIME type, and strict MIME checking is enabled.
Why I'm getting this and how can I solve it?
In my case, I found out that I had a typo in css file name. Thus I was trying to import an non existing file.
You're app is serving fullcalendar.css with the wrong MIME type ('application/json') some how. So, my advise is to dig the problem trusting in the error message.
In my case, I was trying Thymeleaf and WebJars with spring-boot for the first time and following blindly some tutorial I added this:
#Configuration
public class WebConfigurer extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/webjars/**").addResourceLocations("/webjars/");
}
}
Also, my styles were defined in html as below:
<link rel="stylesheet" type="text/css" th:href="#{/webjars/bootstrap/css/bootstrap.min.css}" />
<link rel="stylesheet" type="text/css" th:href="#{/css/main.css}" />
This way, "bootstrap.min.css" and others were given the very same error: "Refused to apply style because its MIME type ('application/json') is not a supported".
I still haven't broken down the reasons for this behavior, but as soon as I realized that spring-boot has an automatic configuration for WebJars, I removed that registration and everything started to work well.
Note: There are some similar tracks with "MIME type ('text/html')" and the reason is usually security filters not allowing the css files and redirecting to html login page. So, keep this in mind and check whether you have some kind of filter/redirect for this request.
Directly put the URL in the browser and see if you can reach it.
For your case, give this url in the browser http://localhost/bower_components/fullcalendar/dist/fullcalendar.css
If you can't reach it, then you have wrong url in your code.
For my case, I had the css file in a directory named css, but in the code I wrote /plugins/css and was getting the same error.
Also, don't forget to give the type="text/css"
So, my code example below:
<head>
<link rel="stylesheet" type="text/css" th:href="#{/css/app.css}">
</head>
If you are using Spring Boot you will not even have to override addResourceHandlers(), just make sure to use th:href and point it to the correct directory.
In my case in the css file
where was a reference to a map file
/*# sourceMappingURL=bootstrap-datepicker.css.map */
that was not present.
I removed the reference to the source map and worked.
You can trying using the relative path to your static content.
<head>
<link rel="stylesheet" type="text/css" href="../css/app.css">
</head>

Spring Boot custom favicon.ico not showing

I know this question has been asked over and over here and there are several solutions. I've tried several of those except the ones that suggests writing you own configuration bean for this. I don't want to do all that just to display a tiny icon it seams overkill. But I can not get it to work. These are the solutions I've tried so far.
just add favicon.ico under static resources and it should work....it doesn't.
spring.mvc.favicon.enabled=false in application.properties, no favicon showed at all (which I guess is the whole point of that).
Tried 2 examples of including the favicon as a link in the html pages. Like so:
<link rel="icon" type="image/png" href="favicon.png" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
Neither of those work.
Tried renaming my own favicon to something else and reference it as above. Does not work.
When inspecting the page in the browser I sometimes get no error at all printed out despite no icon showing, or I get an error saying GET http://localhost:8080/myapp/favicon.png 404 () Where it is refering the type as JSON (which I find strange).
I'm running out of ideas here so if anyone can tell me why this is not working please let me know. Did I perhaps forget one of those magic spring annotations?
This is what my main class looks like.
#SpringBootApplication
#ComponentScan
#Configuration
#EnableWebMvc
public class JobengineMonitorApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(JobengineMonitorApplication.class, args);
}
}
I am using thymeleaf as the template engine
I solved this problem by putting favicon.ico in main/resource/static and adding this lines to my security config
httpSecurity
.authorizeRequests()
.antMatchers( "/favicon.ico").permitAll()
I have this with SpringBoot configuration too and is working
<link rel="shortcut icon" type="image/png" th:href="#{/img/favicon.png}"/>
And the favicon.png under resources/public/img
If anyone faces the same problem using newer version of Spring (in my case spring boot 2.4.4), here's the scenario that worked fine for me:
Put the favicon.ico in the /resources/static folder. I also tried to put it just in the /resourses/ folder and it worked fine as well, so do not worry about the folder that much.
Create a FaviconConfiguration in your configurations folder with the following content:
#Configuration
public class FaviconConfiguration {
#Bean
public SimpleUrlHandlerMapping customFaviconHandlerMapping() {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(Integer.MIN_VALUE);
mapping.setUrlMap(Collections.singletonMap(
"/static/favicon.ico", faviconRequestHandler()));
return mapping;
}
#Bean
protected ResourceHttpRequestHandler faviconRequestHandler() {
ResourceHttpRequestHandler requestHandler
= new ResourceHttpRequestHandler();
requestHandler.setLocations(Collections.singletonList(new ClassPathResource("/")));
return requestHandler;
}
}
In case you use Spring Security don't forget to add antMatcher for your favicon resource by adding the following code to your SpringSecurityConfiguration (as JaneXQ already mentioned above):
.antMatchers("/static/favicon.ico").permitAll()
Use link to your custom favicon explicitly in your html. To do that just put the following link in the <head> section of each of your html pages in the following way (I used thymeleaf in here):
<head>
...
<link rel="icon" type="image/ico" th:href="#{../static/favicon.ico}">
...
</head>
Put your favicon.png under src/main/resources/public and add this to your *.html page exactly in the header section
<link rel="shortcut icon" type="image/png" th:href="#{favicon.png}"/>
I found I had to put my favicon.ico file in:
src/main/resources/public
I saved my favicon which was a simple .png download as src/main/resources/static/favicon.ico
I couldn't get it to display until I tried another browser and it worked fine - so try clearing the browser cache, or try testing on another browser
Ok so this appears to be working now. Of course I managed to get it working just after ranting about it :).
Anyway, what i did was.
Remove #EnableWebMvc from the main class
For added ../ to the href depending on the urls e.g /index was fine but /edit/something.html was not
Sorry for wasting peoples time but hopefully this could be useful for another rookie like me
Try to replace th:href with href. It worked for me.
<link rel="icon" href="/favicon.ico" type="image/ico">
For some reason .ico format was not working. I just placed a png image instead and spring automatically picked the favicon.
I placed the png image in \src\main\resources\public
Spring boot + thymeleaf
I had the same issue and fix it removing #EnableAdminServer annotation

Thymeleaf + CSS+SpringBoot

I have a problem with CSS and Thymeleaf.
In my Spring boot app, I have this structure:
src/main/resource/static/css (for css files)
src/main/resource/static/templates (for html file)
Now, with my html page named ErrorPage and css file named Layout.css, using Thymeleaf I have, in the head of ErrorPage:
<link href="../css/Layout.css" th:href="#{css/Layout.css}" type="text/css" />
But this does not work.
What am I doing wrong?
Move your template folder right under resources:
src/main/resource/static/css (for CSS files);
src/main/resource/templates (for HTML templates).
Then correct the link tag as follows:
<link href="../static/css/Layout.css" th:href="#{/css/Layout.css}" rel="stylesheet" />
Move your template folder right under resources:
src/main/resources/static/css (for CSS files);
src/main/resources/templates (for HTML templates).
Then correct the link tag as follows (relative or absolute):
<link href="../css/firstcss.css" rel="stylesheet">
<link href="/css/secondcss.css" rel="stylesheet">
The old solution with static in front doesn't work for me.
The main culprit of this behaviour is a custom security configuration which is very likely you are doing in your WebSecurityConfigurerAdapter subclass.
If you use SpringBoot 2+ version you should add the following line in your WebSecurityConfigurerAdapter configuration
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()

Loading CSS and JS in default page inside subfolder

I have an ASP.NET web app hosted in a windows dedicated server.
In my app there are many folders. To simplify my problem let's say I have this scenario:
folder
default.aspx
css
js
I would like to setup default.aspx as my default page, meaning, when a user types domain.com, default.aspx is shown.
In order to do this, I edited my web.config file and it works.
The problem is styles and javascripts.
My default.aspx contains this:
<script type="text/javascript" src="js/xxxx.js"></script>
<link href="css/styles.css" rel="stylesheet" type="text/css" />
So the styles and javascripts aren't found.
I really don't want to remove the folder and put everything in the root, and just moving the default.aspx page is not really an option, as I have a MasterPage.
use resolveUrl or a path from root to resolve locations of js and css
<script src='<%= this.ResolveUrl("~/js/xxxx.js") %>' type="text/javascript"></script>
<link href="~/css/styles.css" rel="stylesheet" type="text/css" />
If you're wanting to link to items, you can use the path from the website root. Just place a slash in front of the path.. like this:
<link rel="stylesheet" href="/css/webedit.css" type="text/css" />
You could use Page.ResolveUrl method to get correct paths:
<script type="text/javascript" src='<%= Page.ResolveUrl("~/js/xxxx.js") %>'></script>
<link href='<%= Page.ResolveUrl("~/css/styles.css")' rel="stylesheet" type="text/css" />
For more info see Specifying Paths for Resources.
EDIT: it's mentioned in the comment that this is not working for stylesheets. It's partially true. It won't work for server-side, but will for client-side elements.
It seems your <link> element is located inside a server-side <head> tag, this means ASP.NET treats <link> inside <head> as a server-side controls even if you didn't specify runat="server" attribute there. So you don't need to use a server-side construct in that case:
<link href="~/css/styles.css" rel="stylesheet" type="text/css" />
For ASP.NET WebForms and MVC projects I strongly reccomend moving to Client Dependency framework and let it handle your page dependencies.
For your two dependencies you simply add these declarations to the page:
<CD:CssInclude ID="CssIncludeStyles" runat="server" FilePath="~/css/styles.css" />
<CD:JsInclude ID="JsIncludeXXXX" runat="server" FilePath="~/js/xxx.js" />
This is already cleaner then calling this.ResolveUrl on each dep. declaration.
You can furthermore facilitate the declaration of dependencies by introducing mapped paths in the dependency framework (see documentation for how-to).
An easiest way to start with client dependency is to add it via NuGet to your ASP.NET web site project.
It ensures you never have duplicate dependencies on one page and gives you a control over how dependencies are ordered.

Resources