sec:authorize not working in spring-boot application - spring

I have this index.html on the resources/templates directory of my project:
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" th:href="#{/css/style.css}">
</head>
<body>
<nav sec:authorize="isAnonymous()">
<strong>Hello World!</strong> <a th:href="#{/login}">Login</a>
</nav>
<nav sec:authorize="isAuthenticated()">
<strong th:text="${usuario}"></strong> <a th:href="#{/logout}">Logout</a>
</nav>
<script th:src="#{/js/script.js}"></script>
</body>
</html>
Neither the tags inside sec:authorize="isAnonymous()" or inside sec:authorize="isAuthenticated()" are being display when I run the project and open it in the browser.
I have this application.properties file:
security.basic.enabled=false
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/appdata
spring.datasource.username=kleber
spring.datasource.password=123456
spring.datasource.continue-on-error=true
sprinf.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
spring.servlet.multipart.file-size-threshold=10MB
server.tomcat.max-http-post-size=10MB
and this App class:
#SpringBootApplication
#EnableWebSecurity
#Controller
public class AppApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(AppApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(AppApplication.class);
}
#Bean
public WebSecurityCustomizer ignoringCustomizer() {
return (web) -> web.ignoring().antMatchers("/", "/login", "/logout", "/error", "/css/**", "/js/**", "/img/**");
}
#Bean
public SpringSecurityDialect springSecurityDialect() {
return new SpringSecurityDialect();
}
public UserDetailsService userDetailsService() {
return new UserDetailsService() {
#Autowired
private UsuarioDao usuarioDao;
#Override
public org.springframework.security.core.userdetails.UserDetails loadUserByUsername(String username) {
return usuarioDao.findBy("username", username).get(0);
}
};
}
#RequestMapping(value = "/")
public String index(Model model) {
return "index";
}
#RequestMapping(value = "/login")
public String login(Model model) {
return "login";
}
}
Any hints of what's wrong here?

Did you include Spring Security Thymeleaf extension?
If you're using Maven, the dependency should look like this:
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
Also you will need to enable the Thymeleaf Tags inside the HTML:
<html xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
Heres more on that: https://www.thymeleaf.org/doc/articles/springsecurity.html
I also just realized this is a duplicate: Thymeleaf Spring security integration sec:authorize is not working

Related

Thymeleaf layout fragment not working in Spring Webflux

In spring boot, the layout came out properly with the following settings, but it does not work after changing to webflux.
WebConfig.java
#Configuration
#EnableWebFlux
public class WebConfig implements WebFluxConfigurer, ApplicationContextAware {
ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
}
#Bean
public ITemplateResolver thymeleafTemplateResolver() {
final SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(this.context);
resolver.setPrefix("classpath:templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setCacheable(false);
resolver.setCheckExistence(false);
return resolver;
}
#Bean
public ISpringWebFluxTemplateEngine thymeleafTemplateEngine() {
SpringWebFluxTemplateEngine templateEngine = new SpringWebFluxTemplateEngine();
templateEngine.setTemplateResolver(thymeleafTemplateResolver());
return templateEngine;
}
#Bean
public ThymeleafReactiveViewResolver thymeleafReactiveViewResolver() {
ThymeleafReactiveViewResolver viewResolver = new ThymeleafReactiveViewResolver();
viewResolver.setTemplateEngine(thymeleafTemplateEngine());
return viewResolver;
}
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.viewResolver(thymeleafReactiveViewResolver());
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
registry.addResourceHandler("/resources/**")
.addResourceLocations("/static/")
.resourceChain(true)
.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
}
}
layout_main.html
<body>
<div class="layout-main" ng-app="mainApp">
<header th:replace="fragment/header :: header"></header>
<div class="content">
<section layout:fragment="content"></section>
</div>
</div>
<th:block layout:fragment="js-end"></th:block>
</body>
chat.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layout/layout_main">
<section layout:fragment="content" ng-controller="chatController" class="content-chat-container">
<nav th:replace="~{app/chat/fragment/nav_chat :: nav}"></nav>
<div class="app-wrapper">
</div>
</section>
When opening chat.html, the layout:decorator part is not properly processed, so layout_main is not included and the View appears.

Can's show one login page after logout

My app use frame.
here index.html:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="${appName}">Template title</title>
<link th:href="#{/public/style.css}" rel="stylesheet"/>
</head>
<frameset cols="15%,*">
<frame src="navigator" name="navigator" scrolling="no" noresize/>
<frame src="welcome" name="main"/>
</frameset>
</html>
Here login controller:
#Controller
public class LoginController {
#Value("${spring.application.name}")
private String appName;
private static Logger logger = LogManager.getLogger(LoginController.class);
/*-
#RequestMapping("/")
#ResponseBody
public String index() {
return "Hello!";
}
*/
// Login form
#RequestMapping("/login.html")
public String login(Model model) {
logger.info("open_login.html");
model.addAttribute("appName", appName);
return "login.html";
}
// Login form with error
#RequestMapping("/login-error.html")
public String loginError(Model model) {
model.addAttribute("appName", appName);
model.addAttribute("loginError", true);
return "login.html";
}
}
and here result:
and after success login (show frames)
When I press button logout then call my custom logout handler:
public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler implements LogoutSuccessHandler {
private static Logger logger = LogManager.getLogger(CustomLogoutSuccessHandler.class);
#Override
public void onLogoutSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication)
throws IOException, ServletException {
request.getSession().invalidate();
response.sendRedirect(request.getContextPath() + "/login.html");
}
}
But here result after press Logout
But I need only ONE page (login.html, without frames)
You will have to add below javascript to the login.html.
if ( window.location !== window.parent.location ) {
// We're deeper than one down
window.parent.location=window.location
}

Spring mvc 4 can't render jsp

I'm trying to learn Spring MVC 4 without using the web.xml but instead use the following:
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("*.html");
}
private AnnotationConfigWebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.bookstr.WebConfig");
return context;
}
}
and
#Configuration
#EnableWebMvc
#ComponentScan({ "com.bookstr.*" })
public class WebConfig {
}
For some reason the home.jsp file I have created and placed in the src->main->webapp folder will not be rendered when I use the following controller:
#Controller
public class HomeController {
#RequestMapping(value = "/home", method = RequestMethod.GET)
public String getHome(Model model){
model.addAttribute("home", "Hello world");
return "home";
}
}
And the JSP file is the following:
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Home</title>
</head>
<body>
${home}
</body>
</html>
Update!
Folder structure as requested.
I can see that the HomeController is not getting called.
Register a ViewResolver in your WebConfig:
#Configuration
#EnableWebMvc
#ComponentScan("com.bookstr")
public class WebConfig {
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResover = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
This way, when you return the home from your controller, it will try to render the /WEB-INF/views/home.jsp view. For configuring DispatcherServlet programtically, it's easier to use AbstractAnnotationConfigDispatcherServletInitializer. For example, you simply can:
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/*.html" };
}
}

JSF bean is not interpreted on the *.xhtml page

I am trying to configure JSF/primefaces with Spring boot in my maven project. I am following this example https://github.com/stephanrauh/JSF-on-Spring-Boot which works good.
Issue: when Application is running, the JSF views are shown without data from the back-end.
Here is my *.java classes:
#Configuration
public class WebInitializer extends SpringBootServletInitializer implements ServletContextAware {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
#Bean
public DispatcherServlet dispatcherServlet() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
return dispatcherServlet;
}
#Bean
public ServletRegistrationBean servletRegistrationBean() {
FacesServlet servlet = new FacesServlet();
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(servlet, "*.xhtml");
servletRegistrationBean.setLoadOnStartup(1);
return servletRegistrationBean;
}
#Bean
public ServletListenerRegistrationBean<ConfigureListener> jsfConfigureListener() {
return new ServletListenerRegistrationBean<ConfigureListener>(new ConfigureListener());
}
#Override
public void setServletContext(ServletContext servletContext) {
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString());
}
}
HelloBean class:
#ManagedBean(value = "helloBean")
#ViewScoped
public class HelloBean implements Serializable {
private String hello = "Hello from PrimeFaces and Spring Boot!";
public String getHello() {
return hello;
}
#PostConstruct
public void init() {
System.out.println("---------");
System.out.println(hello);
}
}
index.xhtml file:
<f:view xmlns="http://www.w3c.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:ng="http://xmlns.jcp.org/jsf/passthrough"
xmlns:prime="http://primefaces.org/ui">
<h:head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>#{menuController.title}</title>
<style>
body {font-size:12px; }
</style>
</h:head>
<h:body>
<h:form>
<prime:panel header="What do you see here?" >
<div style="height:50px">
This is a simple PrimeFaces 5 project running on Spring Boot 1.1.4.
</div>
</prime:panel>
<prime:panel header="JSF 2.2 Bean Access">
#{helloBean.hello}
</prime:panel>
</h:form>
</h:body>
</f:view>
Could anyone tell me why helloBean is not displayed on index.xhtml ?
Finally I have found solution to my issue.The problem was in HelloBean.class. I have used incorrect import - import javax.annotation.ManagedBean instead of import javax.faces.bean.ManagedBean;
I've made a different configuration to run Spring Boot + JSF. I think it is simpler. Check it out:
faces-config.xml
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
<lifecycle>
<phase-listener>org.springframework.web.jsf.DelegatingPhaseListenerMulticaster</phase-listener>
</lifecyle>
MyApp.java
#SpringBootApplication
public class MyApp extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyApp.class);
}
#Bean
public ServletRegistrationBean servletRegistrationBean() {
FacesServlet servlet = new FacesServlet();
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(servlet, "*.jsf");
return servletRegistrationBean;
}
}
From Spring Boot 1.2 and above you can set the JSF parameters in the application.properties file, as below:
### JSF CONFIGS ###
server.context_parameters.com.sun.faces.forceLoadConfiguration=true
The Managed Bean of course. Remember not to use the javax.faces.bean package for the bean annotations
MyBean.java
import javax.annotation.ManagedBean;
import javax.faces.view.ViewScoped;
#ManagedBean
#ViewScoped
public class MyBean {
public String getHello() {
return "hello";
}
}
And finally, the view:
<ui:composition
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui"
template="views/templates/basic_template.xhtml"
>
<ui:define name="body_content">
<p:panel header="JSF 2.2 Bean Access">
<h:outputText value="#{myBean.hello}" />
</p:panel>
</ui:define>
</ui:composition>

Spring MVC returns jsp as text/plain content type

I have a problem with Spring MVC and jsp webpage.
When I request a webpage, it returns as text/plain by default. I tried setting the content type as text/html manually at the HttpServletResponse controller, and the web browser reconigzes it, showing it correctly BUT encoding the jsp tags at the body. Example:
JSP:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Error 405 ******* </title>
</head>
<body> asdasdsasad </body>
</html>
Browser receives:
<html>
<body><%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Title</title>
</body>
</html>
I'm using Spring Boot and java web based annotation for configuration. Also, I'm using #EnableAutoConfiguration, and I found that the problem is solved by mapping the sevlet from "/*" to "/".
Because of the java annotation, I had to override the dispatchedServlet (https://github.com/spring-projects/spring-boot/issues/91#issuecomment-27626036) and the configuration class is:
#Configuration
public class DispatcherConfiguration {
#Bean
public ServletRegistrationBean dispatcherRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet());
registration.addUrlMappings("/");
registration.setLoadOnStartup(1);
System.out.println("~~~~~~~ Servlet regristated " + registration.getServletName());
return registration;
}
#Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
Notice that I'm using the #Bean annotation missfollowing the previous comment link, because if not, Spring boot throws an exception. But even if not using the bean annotation, and using an xml the main problem is still here).
This is the Spring MVC configuration file:
#Configuration
#EnableWebMvc
#ComponentScan("es.sfacut")
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
// Maps resources path to webapp/resources
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
registry.addResourceHandler("/images/**").addResourceLocations("/resources/images/");
registry.addResourceHandler("/imgs/**")
.addResourceLocations(Constant.RESOURCE_IMAGES_PATH);
}
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
// resolver.setContentType("text/html");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
// Size in bytes
resolver.setMaxUploadSize(1752300);
return resolver;
}
}
Main class:
#EnableAutoConfiguration
#ComponentScan("es.sfacut")
#EnableJpaRepositories
public class TelocomproMain {
public static void main(String[] args) {
SpringApplication.run(TelocomproMain.class, args);
}
}
Controller:
#RestController
#RequestMapping(value = "/api/")
public class CategoryController {
#RequestMapping(value="test4", method = RequestMethod.GET, produces = "text/plain;charset=UTF-8")
public ModelAndView pageTest4(HttpServletResponse response) {
ModelAndView model = new ModelAndView("elovendo/index");
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
return model;
}
}
Application.properties:
#View resolver
spring.view.prefix= /WEB-INF/views/
spring.view.suffix= .jsp
Not sure if I'm missing something, I'll post everything you need.
Thank you in advance.
Your controller should be a #Controller not a #RestController, otherwise the response will be returned as a string as you observe.
As mentioned already in the comments your custom configuration is not needed at all, you could have a look at the sample provided by the Spring boot team https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-web-jsp.
Had the same issue.
It happens when you have your jsp in directory which is handled by ResourceHandler:
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
This is only for static recourses - img, css, js.
You should move your jsp outside

Resources