Showing specific content for anonymous users with Thymeleaf Security - spring

I'm struggling with the following. I have a nav-bar and i want to show/hide specific content depending on whether the user is anonymous/role_user/role_admin. Here is my html:
<html lang="en" xmlns:th="http://www.thymeleaf.org xmlns:sec="http://www.w3.org/1999/xhtml">
<head>
<title>Beer Tag Home</title>
</head>
<body>
<nav class="navbar" role="navigation" id="mainNav">
<div class="container">
<a class="navbar-brand">Foo App</a>
<div class="navbar-collapse">
<ul class="navbar-nav">
<li class="nav-item"><a About</li>
<li class="nav-item">FAQ</li>
<div class="row" th:if="not${#authentication.isAuthenticated()}">
//this here will not even let spring boot up the app
<li class="nav-item">LOGIN</li>
</div>
<div class="row" <div th:if="${#httpServletRequest.isUserInRole('ROLE_USER')}">
<li class="nav-item">USER PANEL</li>
</div>
</ul>
</div>
</div>
</nav>
Essentially I want to see if a user is Anonymous if so he can only log in. If a user is logged in he can access other content on the page. Here are my gradle dependencies as well:
compile("org.springframework.boot:spring-boot-devtools")
compile 'mysql:mysql-connector-java'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
compile group: 'org.thymeleaf', name: 'thymeleaf', version: '3.0.11.RELEASE'
compile group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-springsecurity4', version: '3.0.4.RELEASE'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
I've read almost all posts on SO regarding this subject, but none of them gives a definitive answer.
Thank you.

To display a block for anonymous only:
<div th:if="!${#request.userPrincipal}">
<!-- content for anonymous -->
</div>

There is also a nice thymeleaf extras module: https://github.com/thymeleaf/thymeleaf-extras-springsecurity
After adding it you can use it like this:
<div sec:authorize="isAuthenticated()">
This content is only shown to authenticated users.
</div>
<div sec:authorize="hasRole('ROLE_ADMIN')">
This content is only shown to administrators.
</div>
<div sec:authorize="hasRole('ROLE_USER')">
This content is only shown to users.
</div>

Related

thymeleaf and spring security dialect, "sec:authorize" not working

I'm using thymeleaf and spring security in project and "sec:authorize" is not working.
So I've edited the code and "sec:~" tag doesn't work itself.
I just add spring security dependency in build.gradle,
still not set security configuration.
I'm trying to resolve this problem using some hours, but I don't know why :(
please help me.
navbar.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<!-- bootstrap-navbar : Supported content[![enter image description here](https://i.stack.imgur.com/CDSjN.png)](https://i.stack.imgur.com/CDSjN.png) -->
<nav th:fragment="navbar" class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<span sec:authentication="name"></span>
<a class="navbar-brand" href="/">Buddy</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul sec:authorize="isAnonymous()" class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="/signin">signin</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/signup">signup</a>
</li>
</ul>
<ul sec:authorize="isAuthenticated()" class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="/board/form">write</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/user/info">info</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/logout">logout</a>
</li>
</ul>
<!-- 네비게이션: 검색창 -->
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
<!-- bootstrap-navbar : Supported content -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3"
crossorigin="anonymous"></script>
</html>
build.gradle
plugins {
id 'org.springframework.boot' version '2.7.5'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'java'
id 'jacoco'
}
group = 'ho'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
// implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
}
tasks.named('test') {
useJUnitPlatform()
}
jacocoTestReport {
reports {
csv.enabled true
xml.enabled true
}
}

xmlns:th="http://www.thymeleaf.org" doesn't work

Thanks!I've finish this problem! I add
protected void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/static/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX + "/static/");
super.addResourceHandlers(registry);
}
in application, then the bug disappears.
Recently, in learning spring boot through the book "spring-boot-in-action", I encountered the following problems
When the program runs, I open the webpage and find that the line "Xmlns: th= 'http://www.thymeleaf.org'" has not been executed, and the CSS file has not been invoked.
Attached below are HTML source code, build. gradle configuration and web controller:
HTML source code:
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Reading List</title>
<link rel="stylesheet" th:href="#{/style.css}"></link>
</head>
<body>
<h2>Your Reading List</h2>
<div th:unless="${#lists.isEmpty(books)}">
<dl th:each="book : ${books}">
<dt class="bookHeadline">
<span th:text="${book.title}">Title</span> by
<span th:text="${book.author}">Author</span>
(ISBN: <span th:text="${book.isbn}">ISBN</span>)
</dt>
<dd class="bookDescription">
<span th:if="${book.description}"
th:text="${book.description}">Description</span>
<span th:if="${book.description eq null}">
No description available</span>
</dd>
</dl>
</div>
<div th:if="${#lists.isEmpty(books)}">
<p>You have no books in your book list</p>
</div>
<hr/>
<h3>Add a book</h3>
<form method="POST">
<label for="title">Title:</label>
<input type="text" name="title" size="50"></input><br/>
<label for="author">Author:</label>
<input type="text" name="author" size="50"></input><br/>
<label for="isbn">ISBN:</label>
<input type="text" name="isbn" size="15"></input><br/>
<label for="description">Description:</label><br/>
<textarea name="description" cols="80" rows="5">
</textarea><br/>
<input type="submit"></input>
</form>
</body>
</html>
gradle configuration
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
web controller prtSc:(I'm not allowed to put a picture, sorry, so I put a link)
<html xmlns="http://www.w3.org/1999/xhtml">
I can find this code, but
xmlns:th="http://www.thymeleaf.org"
disappeared.
https://i.stack.imgur.com/pt5Nj.png

No end tag in Thymeleaf template using Spring Tool Suite Version: 3.8.4.RELEASE

I've generated a Spring Boot web application using Spring Initializr, using embedded Tomcat + Thymeleaf template engine.
I have this Thymeleaf template
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<div th:fragment="common-navbar" class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><a th:text="#{navbar.home.text}" href="/"></a></li>
<li><a th:text="#{navbar.about.text}" href="/about"></a></li>
<li><a th:text="#{navbar.contact.text}" href="/contact"></a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li th:if="${#authorization.expression('!isAuthenticated()')}">
<a th:href="#{/login}" th:text="#{navbar.login.text}" />
</li>
<li th:if="${#authorization.expression('isAuthenticated()')}">
<form id="f" th:action="#{/logout}" method="post" role="form" class="navbar-form">
<button type="submit" th:text="#{navbar.logout.text}" class="btn btn-primary" />
</form>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</body>
</html>
But I have 2 warnings No end tag (</a>). & No end tag (</button>).
If you use spring-boot-starter-thymeleaf dependency, you should add
<properties>
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.1.1</thymeleaf-layout-dialect.version>
</properties>
to your pom.xml.
This forces maven to use Thymeleaf 3. The default Thymeleaf 2 doesn't support pure HTML5.
More informations here: https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-use-thymeleaf-3
Thymeleaf prevents rendering no-valid HTML. What you are doing, using a and button tags with self enclosing, is unvalid according to HTML5 standards.
You can check validation of HTML codes on W3 validator page : https://validator.w3.org
Try an HTML code with self enclosed a and button tags and see the result.
Thymeleaf is not that much tough with validation of HTML codes, though.
You see W3 says a missing title attribute on a button element is an error. But thymeleaf doesn't give an error on that.
Nevertheless; it is important for Thymeleaf that your HTML code shouldn't have missing enclosing tags when it's required.

Maximum function nesting level laravel 5 blade multilevel nesting

I need your help because I have this error when I try to extends a template which extends another one.
Maximum function nesting level of '100' reached, aborting!
writer/dashboard.blade.php
#extends('user.dashboard')
#section('writer-dashboard')
<li><i class="glyphicon glyphicon-calendar"></i>Calendrier</li>
#endsection
user/dashboard.blade.php
#extends('layouts.app')
#section('content')
<div class="row dashboard">
<aside class="col-xs-12 col-lg-2 content-box-large">
<ul class="nav">
<li class="current"><i class="glyphicon glyphicon-home"></i>Dashboard</li>
<li><i class="fa fa-user"></i>Profil</li>
<li><i class="fa fa-graduation-cap"></i>Cours</li>
#yield('writer-dashboard')
</ul>
</aside>
#endsection
layouts/app.blade.php
<!doctype html>
<html lang="fr">
<head>
</head>
<body>
#yield('content')
</body>
</html>
You are creating infinite loop. Check:
In dashboard.blade.php you yield for writer-dashboard template. That template call again dashboard and dashboard call again writer-dashboard.
Instead of #yield directive, use #include. Look for Including Sub-Views in Control Structures' section.

Bootstrap dropdown won't work

I've been messing around with my website for a while now and can't seem to get the dropdown on my navigation to actually drop down. I've read a few questions regarding this and couldn't find something that was this specific.
I have my .js file installed and everything is linked up (as far as I know)
<script src="/js/bootstrap.js" type="text/javascript"></script>
<script src="/js/bootstrap.min.js" type="text/javascript"></script>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="bootstrapindex.html">Student Food</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active">Home</li>
**<li>About</li>
<li class="dropdown">
Recipes<b class="caret"></b>
<ul class="dropdown-menu">
<li>Featured</li>
<li>Latest</li>
<li>Something else here</li>**
</ul>
</li>
</ul>
Can't seem to see why this won't work. If anyone could help that would be amazing.
You're including the Bootstrap JavaScript twice.
Remove one of the following lines:
<script src="/js/bootstrap.js" type="text/javascript"></script>
<script src="/js/bootstrap.min.js" type="text/javascript"></script>
bootstrap.min.js is just a minified version of bootstrap.js; it's the same code.
Try to remove wrapping div <div class="nav-collapse collapse">. I think, dropdown could be hidden by overflow (it was hidden, when I copy-pasted your code snippet).

Resources