I am learning about Spring Security to LDAP server, right now i am trying to make spring authenticate to ldap server. However, spring always uses the embedded server ldap://127.0.0.1:33389/dc=springframework,dc=org instead of my ldap://localhost:389/dc=localdomain,dc=local. I'm trying to configure it using application.properties See below my spring configuration.
WebSecurityConfig.java
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
logger.info("Loading Global Auth Configuration");
auth
.ldapAuthentication();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
logger.info("Configuring HTTP Security.");
// Configure Web Security
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/auth/**").permitAll()
.anyRequest().authenticated();
// disable page caching
http.headers().cacheControl();
}
#Override
public void configure(WebSecurity web) throws Exception {
logger.info("Configuring Web Security HTTP Security.");
// AuthenticationTokenFilter will ignore the below paths
web
.ignoring()
.antMatchers(
HttpMethod.POST,
"/auth"
);
}
}
application.properties
#Ldap Info
spring.ldap.urls=ldap://localhost:389
spring.ldap.anonymous-read-only=true
spring.ldap.username=ldapadm
spring.ldap.password=root123
spring.ldap.base=ou=People,dc=localdomain,dc=local
Tried using above application.properties, still does not work.
application.properties
#Ldap Info
ldap.urls=ldap://localhost:389
ldap.base.dn=dc=localdomain,dc=local
ldap.username=cn=ldapadm,dc=localdomain,dc=local
ldap.password=root123
ldap.user.dn.pattern =uid={0}
I also tried above properties, still does not work.
2018-09-04 00:05:31.515 INFO 9948 --- [ main] s.s.l.DefaultSpringSecurityContextSource : URL 'ldap://127.0.0.1:33389/dc=springframework,dc=org', root DN is 'dc=springframework,dc=org'
2018-09-04 00:05:31.516 INFO 9948 --- [ main] o.s.l.c.support.AbstractContextSource : Property 'userDn' not set - anonymous context will be used for read-write operations
2018-09-04 00:05:31.523 WARN 9948 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.RuntimeException: Could not postProcess org.springframework.security.ldap.authentication.BindAuthenticator#3bc735b3 of type class org.springframework.security.ldap.authentication.BindAuthenticator
2018-09-04 00:05:31.526 INFO 9948 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
for both settings in application.properties, i always get this on my server log
Can anyone make sense of these? i am trying to make it read the application.properties but it always uses the embedded ldap in spring
You can follow a similar approach as in LDAP Authentication with Spring Boot
In application.properties.
ldap.urls=ldap://localhost:389/dc=localdomain,dc=local
In your WebSecurityConfig
#Value("${ldap.urls:ldap://127.0.0.1:33389/dc=springframework,dc=org}")
private String ldapUrls;
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url(ldapUrls)
.and()
.passwordCompare()
.passwordEncoder(new LdapShaPasswordEncoder())
.passwordAttribute("adminpassword");
}
Please note that actual parameters(userDnPatterns etc...) that may be changed according to your LDAP config, i just pointed out how you can configure your LDAP config to connect to an external LDAP
For me this is works
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userSearchFilter("sAMAccountName={0}")
.userDnPatterns("ou=people")
.contextSource()
.url("ldap://127.0.0.1:33389/dc=springframework,dc=org")
.managerDn("ldapadm")
.managerPassword("root123");
}
change "sAMAccountName={0}" to "uid={0}" or whatever your configuration
Related
From what I have read, a filter can be registered either by annotating it with #Component or by registering it in a FilterRegistrationBean. However, I cannot seem to do with just with #Component.
The following code works
//#Component
public class AuthFilter extends OncePerRequestFilter {
#PostConstruct
public void postConstruct() {
System.out.println("*** Loading authFilter");
}
#Override
protected void doFilterInternal(final #NonNull HttpServletRequest httpServletRequest, final #NonNull HttpServletResponse httpServletResponse, final #NonNull FilterChain filterChain) throws ServletException, IOException {
System.out.println("*** calling filter");
filterChain.doFilter(httpServletRequest, httpServletResponse);
System.out.println("*** return from filter");
}
#Bean
public FilterRegistrationBean<AuthFilter> filter() {
final FilterRegistrationBean<AuthFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(this);
return bean;
}
}
However, if I comment out the FilterRegistrationBean method and uncomment the #Component annotation, I get the following stack trace at start-up
{"#timestamp":"2022-03-21T23:00:52.856Z","level":"WARN","message":"Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat","logger_name":"org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext","thread_name":"main","nexusService":"skeleton-Micro-service"}
{"#timestamp":"2022-03-21T23:00:52.868Z","level":"INFO","message":"
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.","logger_name":"org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener","thread_name":"main","nexusService":"skeleton-Micro-service"}
{"#timestamp":"2022-03-21T23:00:52.897Z","level":"ERROR","message":"Application run failed","logger_name":"org.springframework.boot.SpringApplication","thread_name":"main","nexusService":"skeleton-Micro-service","stack_trace":"org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:163)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:447)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1356)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1345)
at com.torchai.service.skeleton.NexusSkeletonServiceApplication.main(NexusSkeletonServiceApplication.java:10)
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:142)
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:104)
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:455)
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:204)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:182)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:160)
... 8 common frames omitted
Caused by: java.lang.IllegalStateException: StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[] failed to start
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.rethrowDeferredStartupExceptions(TomcatWebServer.java:187)
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:126)
... 13 common frames omitted
"}
I haven't been able to figure out what's wrong. If I don't need to specify the order, url or any properties on the FilterRegistrationBean, is it still required?
Update
The filter is in package com.torchai.service.filter; and on my application, class, I have #SpringBootApplication(scanBasePackages = {"com.torchai.service"}). My #PostConstruct method is getting called. So the class is definitely getting loaded
I am currently using spring boot 2.7.0-M1 and following is my dependencies in build.gradle:
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-config'
implementation 'org.springframework.boot:spring-boot-starter-cache'
compileOnly 'org.projectlombok:lombok'
implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
implementation 'io.micrometer:micrometer-registry-datadog:latest.release'
datadogagent("com.datadoghq:dd-java-agent:$datadoghq_dd_version")
implementation("com.datadoghq:dd-trace-api:${datadoghq_dd_version}")
However, when i try to set micrometer bean:
#Configuration
public class MeterRegistryConfig {
#Bean
MeterRegistry meterRegistry(ApplicationContext context) {
DatadogConfig config = new DatadogConfig() {
#Override
public Duration step() {
return Duration.ofSeconds(10);
}
#Override
public String get(String k) {
return null; // accept the rest of the defaults
}
};
return new DatadogMeterRegistry(config, Clock.SYSTEM);
}
}
I am getting a startup error:
2022-02-05 05:07:56.457 ERROR 7897 --- [ restartedMain] o.s.b.web.embedded.tomcat.TomcatStarter : Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. Message: Error creating bean with name 'webMvcMetricsFilter' defined in class path resource [org/springframework/boot/actuate/autoconfigure/metrics/web/servlet/WebMvcMetricsAutoConfiguration.class]: Unsatisfied dependency expressed through method 'webMvcMetricsFilter' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'compositeMeterRegistry' defined in class path resource [org/springframework/boot/actuate/autoconfigure/metrics/CompositeMeterRegistryConfiguration.class]: Unsatisfied dependency expressed through method 'compositeMeterRegistry' parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'meterRegistry' defined in class path resource [com/hbomax/ml/mlsvc/config/MeterRegistryConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.micrometer.core.instrument.MeterRegistry]: Factory method 'meterRegistry' threw exception; nested exception is io.micrometer.core.instrument.config.validate.ValidationException: datadog.apiKey was 'null' but it is required
2022-02-05 05:07:56.504 INFO 7897 --- [ restartedMain] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2022-02-05 05:07:56.520 WARN 7897 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
2022-02-05 05:07:56.541 INFO 7897 --- [ restartedMain] ConditionEvaluationReportLoggingListener :
Here's my application.yaml:
management:
info:
git:
mode: full
metrics:
distribution:
percentiles:
http:
server:
requests: 0.5, 0.95, 0.99
percentiles-histogram:
http:
server:
requests: true
sla:
http:
server:
requests: 200ms, 400ms, 600ms
export:
datadog:
step: 30s
enabled: true
api-key: xxxxxxx
tags:
application: ${spring.application.name}
env: ${spring.profiles}
Can someone help me understand what is the issue? I tried searching around but din't get any solution. I tried replacing api-key with apiKey(I know it's silly) but no success.
Any help folks?
You are using Spring Boot's configuration properties in application.yml but you are also making your own DatadogMeterRegistry that doesn't use those configuration properties, and therefore it will not have the required API key configuration.
You can delete the MeterRegistryConfig class entirely and instead use the DatadogMeterRegistry that Spring Boot will auto-configure from configuration properties because you have the micrometer-registry-datadog dependency on your classpath. See this section of the Spring Boot documentation.
For me, it was just the hierarchy is changed when updated from Spring boot 2 -> 3.
Update the below:
management:
.....
metrics: // Changed to datadog
.....
export: // Changed to metrics
datadog: // Changed to export
step: 30s
enabled: true
api-key: xxxxxxx
.....
To :
management:
.....
datadog:
.....
metrics:
export:
step: 30s
enabled: true
api-key: xxxxxxx
.....
I'm doing a MVC project with spring boot and spring security and jsp. I'm just training my spring and I have the same project running without spring boot. Currently I moved to springboot and when I try to start I get :
2020-05-09 17:28:38.521 INFO 21308 --- [ restartedMain]
o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring
embedded WebApplicationContext 2020-05-09 17:28:38.527 INFO 21308 ---
[ restartedMain] o.s.web.context.ContextLoader : Root
WebApplicationContext: initialization completed in 6813 ms 2020-05-09
17:28:38.753 WARN 21308 --- [ restartedMain]
ConfigServletWebServerApplicationContext : Exception encountered
during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'inMemoryDatabaseShutdownExecutor'
defined in class path resource
[org/springframework/boot/devtools/autoconfigure/DevToolsDataSourceAutoConfiguration.class]:
Unsatisfied dependency expressed through method
'inMemoryDatabaseShutdownExecutor' parameter 0; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'dataSource' defined in class path resource
[org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]:
Bean instantiation via factory method failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method
'dataSource' threw exception; nested exception is
org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException:
Failed to determine a suitable driver class 2020-05-09 17:28:38.769
INFO 21308 --- [ restartedMain]
o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2020-05-09 17:28:38.826 INFO 21308 --- [ restartedMain]
ConditionEvaluationReportLoggingListener :
*************************** APPLICATION FAILED TO START
Description:
Failed to configure a DataSource: 'url' attribute is not specified and
no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
I have no idea what is happening.
application.properties
# JDBC properties
#
app.datasource.url=jdbc:mysql://localhost:3306/web_customer_tracker?useSSL=false&serverTimezone=UTC
app.datasource.username=springstudent
app.datasource.password=springstudent
# Spring Data JPA properties
spring.data.jpa.repository.packages=com.crm.dao
spring.data.jpa.entity.packages-to-scan=com.crm.beans
#
# SECURITY JDBC properties
#
security.datasource.jdbc-url=jdbc:mysql://localhost:3306/spring_security_demo_bcrypt?useSSL=false&serverTimezone=UTC
security.datasource.username=springstudent
security.datasource.password=springstudent
security.datasource.driver-class-name= com.mysql.jdbc.Driver
Configuration:
#Configuration
#EnableWebSecurity
public class DemoSecurityConfig extends WebSecurityConfigurerAdapter {
// add a reference to our security data source
#Autowired
#Qualifier("securityDataSource")
private DataSource securityDataSource;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(securityDataSource);
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("aplicando configuracion");
http.authorizeRequests()
.antMatchers("/employees/showForm*").hasAnyRole("MANAGER", "ADMIN")
.antMatchers("/employees/save*").hasAnyRole("MANAGER", "ADMIN")
.antMatchers("/employees/delete").hasRole("ADMIN")
.antMatchers("/employees/**").hasRole("EMPLOYEE")
.antMatchers("/resources/**").permitAll()
.antMatchers("/showMyLoginPage").permitAll()
.and()
.formLogin()
.loginPage("/showMyLoginPage")
.loginProcessingUrl("/authenticateTheUser")
.permitAll()
.and()
.logout().permitAll()
.and()
.exceptionHandling().accessDeniedPage("/access-denied");
}
}
Configuration:
#Configuration
#EnableJpaRepositories(basePackages={"${spring.data.jpa.repository.packages}"})
public class DemoDataSourceConfig {
#Primary
#Bean
#ConfigurationProperties(prefix="app.datasource")
public DataSource appDataSource() {
return DataSourceBuilder.create().build();
}
#Bean
#ConfigurationProperties(prefix="spring.data.jpa.entity")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, DataSource appDataSource) {
return builder
.dataSource(appDataSource)
.build();
}
#Bean
#ConfigurationProperties(prefix="security.datasource")
public DataSource securityDataSource() {
return DataSourceBuilder.create().build();
}
}
Thanks for your help in advance.
In your properties file...
Change app.datasource.* to spring.datasource.* like below..
# JDBC properties
#
spring.datasource.url=jdbc:mysql://localhost:3306/web_customer_tracker?useSSL=false&serverTimezone=UTC
spring.datasource.username=springstudent
spring.datasource.password=springstudent
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
This error message gives hint that when Soring looks for database URL property.. (they have a fixed property name for it.. like spring.datasource.*) Or Else.. if you are using any embedded database like DB2 then it does not require any url/username/password only the dependency is enough.
In your case, it's not embedded database.. so the property name spring looks for, must be provided correctly.
I have used STS and now I am using IntelliJ Ultimate Edition but I am still getting the same output. My controller is not getting mapped thus showing 404 error. I am completely new to Spring Framework.
DemoApplication.java
package com.webservice.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
HelloController.java
package com.webservice.demo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class HelloController {
#RequestMapping("/hello")
public String sayHello(){
return "Hey";
}
}
Console Output
com.webservice.demo.DemoApplication : Starting DemoApplication on XFT000159365001 with PID 11708 (started by Mayank Khursija in C:\Users\Mayank Khursija\IdeaProjects\demo)
2017-07-19 12:59:46.150 INFO 11708 --- [ main] com.webservice.demo.DemoApplication : No active profile set, falling back to default profiles: default
2017-07-19 12:59:46.218 INFO 11708 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext#238e3f: startup date [Wed Jul 19 12:59:46 IST 2017]; root of context hierarchy
2017-07-19 12:59:47.821 INFO 11708 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8211 (http)
2017-07-19 12:59:47.832 INFO 11708 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2017-07-19 12:59:47.832 INFO 11708 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.15
2017-07-19 12:59:47.944 INFO 11708 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2017-07-19 12:59:47.944 INFO 11708 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1728 ms
2017-07-19 12:59:47.987 INFO 11708 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-07-19 12:59:48.510 INFO 11708 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2017-07-19 12:59:48.519 INFO 11708 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0
2017-07-19 12:59:48.634 INFO 11708 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8211 (http)
2017-07-19 12:59:48.638 INFO 11708 --- [ main] com.webservice.demo.DemoApplication : Started DemoApplication in 2.869 seconds (JVM running for 3.44)
I too had the similar issue and was able to finally resolve it by correcting the source package structure following this
Your Controller classes are not scanned by the Component scanning. Your Controller classes must be nested below in package hierarchy to the main SpringApplication class having the main() method, then only it will be scanned and you should also see the RequestMappings listed in the console output while Spring Boot is getting started.
Tested on Spring Boot 1.5.8.RELEASE
But in case you prefer to use your own packaging structure, you can always use the #ComponentScan annotation to define your basePackages to scan.
Because of DemoApplication.class and HelloController.class in the same package
Locate your main application class in a root package above other classes
Take look at Spring Boot documentation Locating the Main Application Class
Using a root package also allows component scan to apply only on your
project.
For example, in your case it looks like below:
com.webservice.demo.DemoApplication
com.webservice.demo.controller.HelloController
In my case, it was missing the dependency from pom.xml, otherwise everything compiled just fine. The 404 and missing mappings info from Spring logs were the only hints.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
I also had trouble with a similar issue and resolved it using the correct package structure as per below. After correction, it is working properly.
e.g.
Spring Application Main Class is in package com.example
Controller Classes are in package com.example.controller
Adding #ComponentScan(com.webservice) in main class above #SpringBootApplication will resolve your problem. Refer below code
package com.webservice.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#ComponentScan(com.webservice)
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
In my case, I was using #Controller instead of #RestController with #RequestMapping
In my opinion, this visibility problem comes when we leave the component scan to Spring which has a particular way of looking for the classes using standard convention.
In this scenario as the Starter class(DemoApplication)is in com.webservice.demo package, putting Controller one level below will help Spring to find the classes using the default component scan mechanism. Putting HelloController under com.webservice.demo.controller should solve the issue.
It depends on a couple of properties:
server.contextPath property in application properties. If it's set to any value then you need to append that in your request url. If there is no such property then add this line in application.properties server.contextPath=/
method property in #RequestMapping, there does not seem to be any value and hence, as per documentation, it should map to all the methods. However, if you want it to listen to any particular method then you can set it to let's say method = HttpMethod.GET
I found the answer to this. This was occurring because of security configuration which is updated in newer versions of Spring Framework. So i just changed my version from 1.5.4 to 1.3.2
In my case I used wrong port for test request - Tomcat was started with several ones exposed (including one for monitoring /actuator).
In my case I changed the package of configuration file. Moved it back to the original com.example.demo package and things started working.
Another case might be that you accidentally put a Java class in a Kotlin sources directory as I did.
Wrong:
src/main
┕ kotlin ← this is wrong for Java
┕ com
┕ example
┕ web
┕ Controller.class
Correct:
src/main
┕ java ← changed 'kotlin' to 'java'
┕ com
┕ example
┕ web
┕ Controller.class
Because when in Kotlin sources directory, Java class won't get picked up.
All other packages should be an extension of parent package then only spring boot app will scan them by default.
Other option will be to use #ComponentScan(com.webservice)
package structure
👋 I set up 🍃Spring Boot Security in Maven deps. And it automatically deny access to unlogged users also for login page if you haven't change rules for it.
So I prefered my own security system and deleted this dependency.🤓
If you want to use Spring Security. You can wrote WebSecurityConfig like this:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserService userService;
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf()
.disable()
.authorizeRequests()
//Доступ только для не зарегистрированных пользователей
.antMatchers("/registration").not().fullyAuthenticated()
//Доступ только для пользователей с ролью Администратор
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/news").hasRole("USER")
//Доступ разрешен всем пользователей
.antMatchers("/", "/resources/**").permitAll()
//Все остальные страницы требуют аутентификации
.anyRequest().authenticated()
.and()
//Настройка для входа в систему
.formLogin()
.loginPage("/login")
//Перенарпавление на главную страницу после успешного входа
.defaultSuccessUrl("/")
.permitAll()
.and()
.logout()
.permitAll()
.logoutSuccessUrl("/");
}
#Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder());
}
}
from [https://habr.com/ru/post/482552/] (in russian)
So after adding Spring Security (not sure if it is the cause) it appears not only are the default Static Content resolution path null and void, but also any subsequent attempts to map URLs to static content
For example, a vanilla Spring Boot Application without a WebSecurityConfigurerAdapter would map /GET localhost:8080/index.html to ResourceHttpRequestHandler with default configured static content locations such as classpath:META-INF/resources and classpath:static/
Thus index.html located in one of these classpath locations are automatically served.
With a WebSecurityConfigurerAdapter however, I get 405s ... and no matter what I do ... it appears the handler registry will not contain a mapping to the aforementioned ResourceHttpRequestHandler locations
For example
Attempt to Add mapping explicitly
Use ResourceHandlerRegistry
#Configuration
public class ServletConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/index.html").addResourceLocations("classpath:statc/index.html");
super.addResourceHandlers(registry);
}
}
Here are the TRACE logs
2017-07-17 12:12:21.742 DEBUG 23566 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/]
2017-07-17 12:12:21.755 DEBUG 23566 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /
2017-07-17 12:12:21.760 DEBUG 23566 --- [nio-8080-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported
2017-07-17 12:12:21.768 DEBUG 23566 --- [nio-8080-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Invoking #ExceptionHandler method: public final org.springframework.http.ResponseEntity<java.lang.Object> org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler.handleException(java.lang.Exception,org.springframework.web.context.request.WebRequest)
Is this a known and frequently encountered issue when dealing with Spring Security?
Or maybe this is not expected and unrelated to Spring Security? I've gotten the entire setup to work many times before, the only thing new is Spring Security
Here is the SecurityConfiguration
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailService userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
final DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder(new StandardPasswordEncoder());
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
/*
it is important to set the default userDetailsService on AuthenticationManagerBuilder
*/
auth.authenticationProvider(daoAuthenticationProvider).userDetailsService(userDetailsService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
org.springframework.security.web.authentication.AuthenticationSuccessHandler authenticationSuccessHandler = new AuthenticationSuccessHandler();
http
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
.and()
.authorizeRequests()
.antMatchers("/index.html").permitAll()
.antMatchers("/api/security/**")
.hasAuthority("ADMIN")
.antMatchers("/api/portfolios/**", "/api/trades/**", "/api/user/**", "/api/init")
.authenticated()
.and()
.formLogin()
.successHandler(authenticationSuccessHandler)
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.rememberMe()
.and()
.logout()
.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK));
}
}
Note that the start-up logs show both the default static content handler mapping and my explicit mapping to be both present and configured ... they are just not there when the actual request is made:
2017-07-17 12:25:57.088 DEBUG 23702 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Found resource handler mapping: URL pattern="/**/favicon.ico", locations=[ServletContext resource [/], class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], class path resource []], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver#23707d5d]
2017-07-17 12:25:57.089 DEBUG 23702 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Found resource handler mapping: URL pattern="/index.html", locations=[class path resource [statc/index.html]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver#5fa49615]
2017-07-17 12:25:57.089 DEBUG 23702 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Found resource handler mapping: URL pattern="/webjars/**", locations=[class path resource [META-INF/resources/webjars/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver#7921eb37]
2017-07-17 12:25:57.089 DEBUG 23702 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Found resource handler mapping: URL pattern="/**", locations=[ServletContext resource [/], class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver#3fdb9c55]
EDIT
Digging Deeper
It appears there is a PartialMatchHelper in RequestMappingInfoHandlerMapping.java:195 on URL:[], method: PUT which will match every single request!
Kind of small mistake on my part - but has huge implications (after learning how Spring MVC framework works internally)
I had accidentally added a controller like this
#RestController("registration")
public class RegistrationController { ... }
When I meant
#RestController
#RequestMapping("registration")
public class RegistrationController {...}
so my registration REST end point would not have worked ... clearly BUT ... the former configuration also unwitting affected static content resolution by placing an empty URL:[], METHOD: PUT/POST or whatever into RequestMappingHandlerMapping which is one of the handler mappings that can take precedence over static Resource mappings
So the moral of the story is:
debug DispatcherServlet.java to see which handler mapping is truly being used