I'm making a web app using Spring 4, the Spring security module and tomcat 8. I'm trying to include some css files and js files in a .jsp file, but it's not working. When I check in the sources tag in Chrome the content of the css seems to be a log in form. I suspect that it may have something to do with spring security.
My css file is included like this in the .jsp
<link href="<c:url value='resources/css/materialize.min.css' />" rel="stylesheet"
type="text/css"></link>
This is the WebConfig file
#Configuration
#ComponentScan(basePackages = "mypackage")
#EnableWebMvc
#EnableTransactionManagement
public class WebAppConfig extends WebMvcConfigurerAdapter {
#Bean
public InternalResourceViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Autowired
#Bean
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory){
HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
return transactionManager;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
This is the SecurityConfig file
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/js/**", "/resources/css/**", "/resources/img/**", "/resources/font/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().loginPage("/signin")
.failureUrl("/signin?param.error=bad_credentials")
.and().logout().logoutUrl("/signout")
.and().authorizeRequests()
.antMatchers("/favicon.ico", "/resources/css/**", "/resources/font/**",
"/resources/js/**", "/auth/**", "/signin/**", "/signup/**", "/disconnect/facebook").permitAll()
.antMatchers("/**").authenticated()
.and()
.rememberMe().
and().csrf();
}
}
According to other answers here in stackoverflow it should work with the code that I have but the css only returns this:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:social="http://spring.io/springsocial"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layout">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<div id="content" >
<form id="signin" action="signup" method="post">
<input type="hidden" name="" value=""/>
<div class="formInfo">
</div>
<fieldset>
<label for="login">Email</label>
<input id="login" name="email" type="text" size="25"></input>
<label for="Nombre">Email</label>
<input id="nombre" name="nombre" type="text" size="25"></input>
<label for="password">Password</label>
<input id="password" name="contrasena" type="password" size="25"></input>
</fieldset>
<button type="submit">Sign In</button>
<p>Or you can signin with a new account.</p>
</form>
</div>
All my css and js files are inside WebContent/resources
I solved the problem, apparently there was an ambiguous routing in one of my controllers, so when I tried to access a url that started with "/resources" it routed it to the controller, and thus returned a .jsp instead of the css/js/image. My original controller binded the url in the #Controller, and left the #RequestMapping without indicating the route.
#Controller("/signup")
public class SignUpController {
#RequestMapping(method=RequestMethod.GET)
public String signUpForm(){
...
}
#RequestMapping(method=RequestMethod.POST)
public String crearUsuario(HttpServletRequest request){
...
}
So I changed the #Controller annotation, and put the url in each #RequestMapping like this:
#Controller
public class SignUpController {
#RequestMapping(value="/signup", method=RequestMethod.GET)
public String signUpForm(){}
#RequestMapping(value="/signup",method=RequestMethod.POST)
public String crearUsuario(HttpServletRequest request){}
}
Related
So I am trying to creating simple Login Page with help of the Spring Boot and Security. So what I currently have is custom login page and in memory authentication with one user and role.
The problem is that when I am entering proper user/password spirng is not authenticating it as valid data, and redirecting me again to login page, but this time with: /login#error
On client side I am using thymeleaf.
form snippet:
<form th:action="#{/perform_login}" method="post">
<input name="user" placeholder="Username" /> <br />
<input name="pass" placeholder="Password" /> <br />
<input type="submit" value="Login" />
</form>
Configuration class:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()//
.withUser("root").password("root").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() //
.antMatchers("/").hasRole("USER") //
.antMatchers("/login*").permitAll().and() //
.formLogin() //
.loginPage("/login")//
.loginProcessingUrl("/perform_login")//
.and()//
.logout()//
.permitAll();
}
}
And controller is simple
#Controller
#RequestMapping("/login")
public class LoginController {
#GetMapping
public String getLoginPage() {
return "login";
}
}
Any idea what I am doing wrong?
The easiest way (for me) is to make a #Bean and use WebSecurityConfigurerAdapter and implement WebMvcConfigurer to configure everything with few steps. This is the smallest example ever made:
#Configuration
#SpringBootApplication
public class DemoApplication implements WebMvcConfigurer {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Controller
public class HomeController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model, Authentication authentication, Principal principal) {
if (authentication == null) {
return "forward:/login";
} else {
model.addAttribute("user", principal.getName());
return "home";
}
}
}
#Bean
public WebSecurityConfigurerAdapter webSecurityConfig() {
return new WebSecurityConfigurerAdapter() {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.anyRequest().authenticated()
.and().formLogin().loginPage("/login")
.defaultSuccessUrl("/")
.permitAll()
.and().logout().permitAll();
http.headers().frameOptions().disable();
}
#Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.authenticationProvider(new AuthenticationProvider() {
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
if (username.equals("username") && password.equals("password")) {
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new UsernamePasswordAuthenticationToken(username, password, grantedAuthorities);
}
throw new AuthenticationServiceException("Invalid credentials.");
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
});
}
};
}
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/login").setViewName("login");
}
}
You said that you are using thymeleaf so lets say your login.html form will be something like this:
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>login example</title>
</head>
<body>
<form th:action="#{/login}" method="post">
<input name="username" placeholder="Username"/> <br/>
<input name="password" placeholder="Password"/> <br/>
<input type="submit" value="Login"/>
</form>
</body>
</html>
And the home.html page when you are logged in:
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>home page</title>
</head>
<body>
Hello, <span th:text="${user}"></span><br>
sign out
</body>
</html>
I would like to configure Spring Security for Hawt.io with embedded tomcat. After custom login with (user and password) Hawt.io login is asking to authenticate.But Hawt.io authentication is disabled in code and in config. If I remove MvcConfig and WebSecurityConfig with security.basic.enable= false then without any authentication which works.But
I want to authenticate with custom username and password which is
working after that Hawt.io is also asking the credentials though that
part is disabled.
Please help me to resolve this.
application.properties
hawtio.authenticationEnabled = false
management.security.enabled=false
security.basic.enable= true
security.ignored= /**
login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example </title>
</head>
<body>
<div th:if="${param.error}">
Invalid username and password.
</div>
<div th:if="${param.logout}">
You have been logged out.
</div>
<form th:action="#{/login}" method="post">
<div><label> User Name : <input type="text" name="username"/> </label></div>
<div><label> Password: <input type="password" name="password"/> </label></div>
<div><input type="submit" value="Sign In"/></div>
</form>
</body>
</html>
MvcConfig.java
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
WebSecurityConfig.java
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/","/hawtio").permitAll().anyRequest().authenticated().and()
.formLogin().loginPage("/login")
.permitAll().and().logout().permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
}
Application.java
#SpringBootApplication
#EnableHawtio
public class Application {
public static void main(String[] args) {
System.setProperty(AuthenticationFilter.HAWTIO_AUTHENTICATION_ENABLED, "false");
SpringApplication.run(Application.class, args);
}
}
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>io.hawt</groupId>
<artifactId>hawtio-springboot</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>io.hawt</groupId>
<artifactId>hawtio-core</artifactId>
<version>1.5.6</version>
</dependency>
</dependencies>
Update:
Connect to dummy camel app like below login for again comes on giving credentials going to 404 error page.
The following changes are required to make hawtio work with Spring Security and Spring Boot. You can find a working example here. However, I wasn't able to update the username in hawtio menubar.
Configure Spring Security
Configure Spring security for application in a standard way except for
a few changes specfic to hawtio:
Disable hawtio authentication,
#SpringBootApplication
#EnableHawtio
#ComponentScan(basePackages = {"com.basaki"})
public class Application {
public static void main(String[] args) {
System.setProperty(AuthenticationFilter.
HAWTIO_AUTHENTICATION_ENABLED,"false");
SpringApplication.run(Application.class, args);
}
}
Disable Cross-Site Request Forgery (CSRF) in your application.
Make sure the logout request URL matches the /hawtio/auth/logout/*.
This is the URL used by hawtio to invalidate a session.
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
...
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").permitAll()
.anyRequest().authenticated()
.and().formLogin().loginPage("/login")
.failureUrl("/login?error")
.permitAll()
.and().logout().logoutRequestMatcher(
new AntPathRequestMatcher(
"/hawtio/auth/logout/*"))
.logoutSuccessUrl("/login?logout")
.and().csrf().disable();
}
...
}
Login Page
Since you are using a form login, you will be needing a custom login page. In this example, a login.html is used.
Configure the /login request to match view login.html
#Configuration
public class SpringMvcConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
...
}
Updating hawtio's login.html
Once you log out from the hawtio page, it takes you to its own login page. Since it's a single page application with AngularJS, you need to replace this partial page with your own custom AngularJS based login page.
In this example, a login-hawtio.html page is used.
<div ng-controller="LoginPlugin.LoginController">
<h1 style="color: #78ab46;">Sign in</h1>
<form action="/login" method="post">
<div>
<label style="font-weight: 700; padding-right: 15px;
padding-left: 15px;">Username:
<input id="username" type="text" name="username"
placeholder="Username"/>
</label>
</div>
<div>
<label style="font-weight: 700; padding-right: 15px;
padding-left: 15px;">Password:
<input id="password" type="password"
name="password" required
placeholder="Password"/>
</label>
</div>
<div>
<button type="submit" class="btn btn-default">Sign In</button>
</div>
</form>
</div>
A controller to replace the existing hawtio login page.
#Controller
public class HawtioController {
private ResourceLoader loader;
#Autowired
public HawtioController(ResourceLoader loader) {
this.loader = loader;
}
#RequestMapping(value = "/hawtio/app/core/html/login.html", method = RequestMethod.GET,
produces = "text/html;charset=UTF-8")
public void getHawtioLoginHtml(HttpServletResponse response) {
String location = "classpath:/templates/login-hawtio.html";
try {
String body = getResource(location);
response.setStatus(HttpStatus.OK.value());
response.getWriter().write(body);
response.getWriter().flush();
response.getWriter().close();
} catch (IOException e) {
response.setStatus(HttpStatus.NOT_FOUND.value());
}
}
...
}
hawtio Login Plugin
A custom hawtio plugin is needed to have your own AngularJS login controller, LoginPlugin.LoginController. It's used for redirecting to hawtio's home page after you are logged in from hawto's login page.
#Configuration
public class HawtioConfiguration {
#Bean
public HawtPlugin samplePlugin() {
return new HawtPlugin("login-plugin",
"/hawtio/plugins",
"",
new String[]{"plugin/js/login-plugin.js"});
}
}
The login-plugin.js is located under resources/app/webapp/plugin/js folder.
var LoginPlugin = (function(LoginPlugin) {
LoginPlugin.pluginName = 'login-plugin';
LoginPlugin.log = Logger.get('LoginPlugin');
LoginPlugin.module = angular.module('login-plugin', ['hawtioCore'])
.config(function($routeProvider) {
$routeProvider.
when('/home', {
templateUrl: '/hawtio/index.html'
});
});
LoginPlugin.module.run(function(workspace, viewRegistry, layoutFull) {
LoginPlugin.log.info(LoginPlugin.pluginName, " loaded");
viewRegistry["login-plugin"] = layoutFull;
workspace.topLevelTabs.push({
id: "LoginPlugin",
content: "Login Plugin",
title: "Login plugin loaded dynamically",
isValid: function(workspace) { return true; },
href: function() { return "#/login-plugin"; },
isActive: function(workspace) {
return workspace.isLinkActive("login-plugin"); }
});
});
LoginPlugin.LoginController = function($scope, $rootScope, $http) {
var fullUrl = "/hawtio/index.html";
$http({method: 'GET', url: fullUrl});
};
return LoginPlugin;
})(LoginPlugin || {});
hawtioPluginLoader.addModule(LoginPlugin.pluginName);
Hi I Have such images in resources/static and put them into my index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8"/>
<title>Test</title>
</head>
<body>
<div>
<form method="POST" enctype="multipart/form-data" action="/">
<p>
<img src="../static/image1.png" alt="Image 1"/>
<img src="../static/image2.png" alt="Image 2"/>
<tr>
<td></td>
<td><input type="submit" value="Test"/></td>
</tr>
</p>
</form>
</div>
<div th:if="${success}">
<img src="/static/result.png"/>
</div>
</body>
</html>
Then, in ResourceConfig
#Configuration
#EnableWebMvc
#ComponentScan
public class ResourceConfig extends WebMvcConfigurerAdapter {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/images/",
"classpath:/static/", "classpath:/public/" };
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/webjars/**")) {
registry.addResourceHandler("/webjars/**").addResourceLocations(
"classpath:/META-INF/resources/webjars/");
}
if (!registry.hasMappingForPattern("/**")) {
registry.addResourceHandler("/**").addResourceLocations(
CLASSPATH_RESOURCE_LOCATIONS);
}
}
}
The problem is, that application doesn't see my images. I've added resource handler, but it hasn't worked. The output is
Output
This #Override method addResourceHandlers shows Spring Framework where are all you static resources. So... your folder which contains images which are also a static resource must be under your root static resource handler. Set it like this and create this folder under WebContent folder in your project.
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**").addResourceLocations("/assets/");
}
This line in your html template
<div th:if="${success}">
makes me think you are using Thymeleaf as your template engine. If that is that case, you should use this to refer to static content:
<img th:src="#{/result.png}"}/>
if your png file is indeed in the root of your static folder.
Hi I'm currently trying to set up a simple login page using Spring Boot Security but whenever I try to access the login view I get a 404 "page not found" error.
Security Config:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
}
}
Login view, using freemarker (located at main/resources/templates/login.ftl):
<body class="login">
<div>
<div class="login_wrapper">
<div class="animate form login_form">
<section class="login_content">
<form>
<h1>Login Form</h1>
<div>
<input type="text" class="form-control" placeholder="Username" required="" />
</div>
<div>
<input type="password" class="form-control" placeholder="Password" required="" />
</div>
<div>
<a class="btn btn-default submit" href="/units">Log in</a>
</div>
<div class="clearfix"></div>
</form>
</section>
</div>
</div>
</div>
</body>
Anyone know what I'm doing wrong? Thanks for the help!
You need to have a view controller for /login. either write a controller for that or following will do.
#EnableWebMvc
#ComponentScan("package_name")
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
// ...
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
To setup view rosolver:
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".ftl");
return resolver;
}
Now put your ftl files inside webapp/WEB-INF/pages directory. You're all set.
I have a form like this:
<form method="post" accept-charset="utf-8">
<fieldset>
<legend>Send a Message To Future</legend>
<label for="fullName">Your Name:</label>
<input type="text" name="fullName" id="fullName">
<br/>
<label for="message">Your Message:</label>
<textarea name="message" rows="3" id="message" style="width: 400px"></textarea>
<br/>
<button type="submit" class="btn">Submit</button>
</fieldset>
</form>
which is handled in
#RequestMapping(value = "/", method = RequestMethod.POST)
public String postMessage(Model model, MessageToFuture messageToFuture) {
String fullName = messageToFuture.getFullName();
String message = messageToFuture.getMessage();
System.out.println(fullName + " " + message);
if (fullName.length() == 0 || message.length() == 0) {
System.out.println("No no no!");
model.addAttribute("formNotFull", "Please fill in all the fields!");
return "index";
} else {
toFutureRepository.addMessageToFuture(messageToFuture);
return "redirect:/";
}
}
and in web.xml I have:
<page-encoding>UTF-8</page-encoding>
also the header of my jsp has:
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
And finally my configuration for Spring:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "biz.tugay.forFuture.web")
public class ServletConfigClass extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver =
new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
When I post the characters such as 'ğ', if the application is deployed to Tomcat, I am seeing weird characters. But if I run jetty, all is fine.
server.xml for Tomcat has:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8" />
What am I missing?
I tried both with Tomcat 7 and 8.