How to allow anonymous access to endpoint - spring-security

I have a spring cloud architecture and I can't allow anonymous access to an endpoint.
Here is my code:
Gateway =============================
Application:
#SpringBootApplication
#EnableZuulProxy
#EnableEurekaClient
#EnableResourceServer
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
#Bean
public FilterRegistrationBean<?> corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<?> bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
}
Pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.geminiald</groupId>
<artifactId>gateway</artifactId>
<version>1.0.0</version>
<name>gateway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
bootstrap.properties:
spring.cloud.config.name=gateway
spring.cloud.config.discovery.service-id=config
spring.cloud.config.discovery.enabled=true
eureka.client.serviceUrl.defaultZone=http://localhost:8082/eureka/
application.properties:
security.oauth2.resource.user-info-uri=http://localhost:8083/user
Furthermore, I have an auth-service ====================
Application:
#SpringBootApplication
#EnableEurekaClient
#EnableAuthorizationServer
#EnableResourceServer
#EntityScan(basePackages = { "com.geminiald.authservice.models" })
#EnableJpaRepositories(basePackages = { "com.geminiald.authservice.repositories" })
public class AuthServiceApplication {
public static void main(String[] args) {
SpringApplication.run(AuthServiceApplication.class, args);
}
}
#Configuration
public class AuthorizationServerConfig
extends AuthorizationServerConfigurerAdapter {
private BCryptPasswordEncoder passwordEncoder;
#Autowired
public AuthorizationServerConfig(
#Lazy BCryptPasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
#Autowired
private AuthSettings settings;
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerSecurityConfigurer security)
throws Exception {
security.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
clients.inMemory().withClient(settings.getClient())
.authorizedGrantTypes(
settings.getAuthorizedGrantTypes())
.authorities(settings.getAuthorities())
.scopes(settings.getScopes())
.resourceIds(settings.getResourceIds())
.accessTokenValiditySeconds(settings
.getAccessTokenValiditySeconds())
.secret(passwordEncoder.encode(settings.getSecret()));
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
#Configuration
public class AuthenticationMananagerProvider
extends WebSecurityConfigurerAdapter {
#Autowired
private CustomUserDetailsService userDetailsService;
#Autowired
private BCryptPasswordEncoder encoder;
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
public void authenticationManager(AuthenticationManagerBuilder builder,
UserRepository repository) throws Exception {
builder.userDetailsService(userDetailsService).passwordEncoder(encoder);
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
BCryptPasswordEncoder bCryptPasswordEncoder =
new BCryptPasswordEncoder();
return bCryptPasswordEncoder;
}
#Bean
public FilterRegistrationBean<?> corsFilter() {
UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<?> bean =
new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
}
application.properties:
# H2 Database configuration
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.datasource.initialization-mode=always
bootstrap.properties:
spring.cloud.config.name=auth-service
spring.cloud.config.discovery.service-id=config
spring.cloud.config.discovery.enabled=true
eureka.client.serviceUrl.defaultZone=http://localhost:8082/eureka/
I have a Dc-tool-box-service:
Application ==========
#SpringBootApplication
#EnableEurekaClient
#EnableResourceServer
#EntityScan(basePackages = { "com.geminiald.dctoolbox.models" })
#EnableJpaRepositories(basePackages = { "com.geminiald.dctoolbox.repositories" })
public class DcToolBoxServiceApplication {
public static void main(String[] args) throws IOException {
SpringApplication.run(DcToolBoxServiceApplication.class, args);
}
}
bootstrap.properties:
spring.cloud.config.name=dc-tool-box-service
spring.cloud.config.discovery.service-id=config
spring.cloud.config.discovery.enabled=true
eureka.client.serviceUrl.defaultZone=http://localhost:8082/eureka/
application.properties:
# H2 Database configuration
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.datasource.initialization-mode=always
spring.servlet.multipart.max-file-size=-1
spring.servlet.multipart.max-request-size=-1
security.oauth2.resource.user-info-uri=http://localhost:8083/user
and there, you can see all *.properties file from the configuration service:
auth-service:
spring.application.name=auth-service
server.port=8083
eureka.client.region = default
eureka.client.registryFetchIntervalSeconds = 5
eureka.client.serviceUrl.defaultZone=http://localhost:8082/eureka/
gateway:
spring.application.name=gateway
server.port=8000
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=60000
zuul.host.connect-timeout-millis= 15000
zuul.host.socket-timeout-millis= 60000
ribbon.ReadTimeout= 60000
ribbon.ConnectTimeout= 60000
eureka.client.region = default
eureka.client.registryFetchIntervalSeconds = 5
zuul.routes.discovery.path=/discovery/**
zuul.routes.discovery.sensitive-headers=Set-Cookie,Authorization
zuul.routes.discovery.url=http://localhost:8082
hystrix.command.discovery.execution.isolation.thread.timeoutInMilliseconds=600000
zuul.routes.auth-service.path=/auth-service/**
zuul.routes.auth-service.sensitive-headers=Set-Cookie
hystrix.command.auth-service.execution.isolation.thread.timeoutInMilliseconds=600000
zuul.routes.dc-tool-box-service.path=/dc-tool-box-service/**
zuul.routes.dc-tool-box-service.sensitive-headers=Set-Cookie
hystrix.command.dc-tool-box-service.execution.isolation.thread.timeoutInMilliseconds=600000
dc-tool-box-service:
spring.application.name=dc-tool-box-service
server.port=8086
eureka.client.region = default
eureka.client.registryFetchIntervalSeconds = 5
eureka.client.serviceUrl.defaultZone=http://localhost:8082/eureka/
In order to do that, I have two endpoints in the dc-tool-box-service: /persons/signup and /dossiers.
I would like to keep the security on /dossiers, but /persons/signup should be anonymous. So anybody can access without authentication.
That is what I in gateway:
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.antMatchers("/dc-tool-box-service/persons/signup").anonymous();
}
}
In in my Postman, I can access the /dossiers using my token, but I get the message:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
when I try to access /persons/signup without providing a property Authorization in my header.
Could someone help me please?! I would be thankful.

You need to use permitAll() instead of anonymous().
Replace: .antMatchers("/dc-tool-box-service/persons/signup").anonymous();
With: .antMatchers("/dc-tool-box-service/persons/signup").permitAll();
This will authorize all users, anonymous and logged in.
Problem with anonymous() is that, only users that have ROLE_ANONYMOUS would able to access that endpoint.
EDIT: Security order matters: It still doesn't work because your first security constraint is that any request to your application should be authenticated, then you have configured to allow /signup request. Change the order of these permissions.
http.authorizeRequests()
.antMatchers("/dc-tool-box-service/persons/signup").permitAll()
.and()
.authorizeRequests()
.anyRequest().authenticated();

Related

Spring Security (5.7.3): this.authenticationManager is null

I'm trying POST requests to login to the page with JWT Authentication.
I had initially tried to do JWT Authentication using WebSecurityConfigurerAdapter. But WebSecurityConfigurerAdapter is deprecated. I then tried to integrate it according to the new usage.But When I send POST request in Postman, I m getting this error.
"org.springframework.security.authentication.AuthenticationManager.authenticate(org.springframework.security.core.Authentication)" because "this.authenticationManager" is null
My Dependencies are:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.project</groupId>
<artifactId>questapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>questapp</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
My Controller Class is:
#RestController
#RequestMapping("/auth")
public class AuthenticationController {
private AuthenticationManager authenticationManager;
private JwtTokenProvider jwtTokenProvider;
#PostMapping("/login")
public String login(#RequestBody UserRequest userLoginRequest) {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userLoginRequest.getUserName(), userLoginRequest.getPassword());
Authentication auth = authenticationManager.authenticate(authenticationToken);
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
String jwtToken = jwtTokenProvider.generateJwtToken(auth);
return "Bearer "+jwtToken;
}
}
My SecurityConfig Class is:
#Configuration
#EnableWebSecurity
#RequiredArgsConstructor
public class SecurityConfig {
private final UserDetailsService jwtUserDetailsService;
private final JwtAuthenticationEntryPoint handler;
#Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
#Bean
public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder.userDetailsService(jwtUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
return authenticationManagerBuilder.build();
}
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception{
httpSecurity
.cors()
.and()
.csrf().disable()
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.exceptionHandling().authenticationEntryPoint(handler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(HttpMethod.GET,"/auth/**")
.permitAll()
.antMatchers("/auth/**")
.permitAll()
.anyRequest().authenticated();
return httpSecurity.build();
}
}
Can anyone tell me where I made a mistake?

What should be used instead of SpringBootServletInitializer deprecated in 1.4.0.RELEASE

I've had developed the spring-security-jsp-authorize example. In this example I was using the spring-boot-starter-parent version 1.3.7.RELEASE till that version program was not giving any deprecation error for SpringBootServletInitializer. What's is the replacement of import org.springframework.boot.context.web.SpringBootServletInitializer in spring-boot-starter-parent in version 1.4.0.RELEASE?
Application.java
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
SecurityConfig.java
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("john").password("123").roles("USER")
.and()
.withUser("tom").password("111").roles("ADMIN");
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
.and().formLogin().permitAll();
}
}
MvcConfig.java
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
public MvcConfig() {
super();
}
#Override
public void addViewControllers(final ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/").setViewName("forward:/index");
registry.addViewController("/index");
}
}
It is stated in docs for Spring Boot 1.4 > org.springframework.boot.context.web:
Deprecated. as of 1.4 in favor of
org.springframework.boot.web.support.SpringBootServletInitializer
Just change the deprecated import to this new package.
You can use WebMvcConfigurer interface.
public class Configuration implements WebMvcConfigurer {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(mappingJackson2HttpMessageConverter());
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurerconfigurer) {
configurer.enable();
}
}

How to change Swagger-ui URL?

I have tried to change the swagger URL, right now i have "http://localhost:8080/context-root/rest/swagger-ui.html", i want it to be "http://localhost:8080/swagger". I tried using the DOCKET.Host("swagger"), but browser is spinning. And its not loading screen.
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.4.0</version>
</dependency>
Can any one help with that?
Have you tried Path Provider ?
#Configuration
#EnableSwagger2
#Profile({"!production"})
public class SwaggerConfiguration extends WebMvcConfigurerAdapter {
#Autowired
private ServletContext servletContext;
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.host("localhost")
.pathProvider(new RelativePathProvider(servletContext) {
#Override
public String getApplicationBasePath() {
return "/swagger";
}
})
.protocols(new HashSet<String>(Arrays.asList(protocols)))
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}

spring boot custom login page

I am trying to add a custom login page for my boot strap application. I was following this tutorial. I couldn't make work with my custom login page.
Here is my pom.xml:
...
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<scope>test</scope>
</dependency>
...
MvcConfig.java
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/index.html");
registry.addViewController("/login").setViewName("login");
}
}
FrontendApp.java:
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
import ch.qos.logback.classic.Logger;
#SpringBootApplication
#Import(value = MvcConfig.class)
public class FrontendApp {
private static Logger logger = (Logger) LoggerFactory.getLogger(FrontendApp.class);
public static void main(String[] args) {
SpringApplication app = new SpringApplication(FrontendApp.class);
app.run(args);
}
}
SecurityConfiguration.java
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
#Autowired
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(this.customAuthenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**").permitAll()
.antMatchers("/resources/**").permitAll()
.antMatchers("**").permitAll()
.antMatchers("/login").permitAll()
.anyRequest().authenticated().and()
.formLogin()
.loginPage("/login");
}
}
I opened all the url's so Ican just check whether I can see /login or not.
CustomAuthenticationProvider.java
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
private static final Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);
public CustomAuthenticationProvider() {
logger.info("*** CustomAuthenticationProvider created");
}
#Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if(authentication.getName().equals("karan") && authentication.getCredentials().equals("saman")) {
List<GrantedAuthority> grantedAuths = new ArrayList<>();
grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
return new UsernamePasswordAuthenticationToken(authentication.getName(), authentication.getCredentials(), grantedAuths);
} else {
return null;
}
}
}
When I try localhost:8080/login I will get the following error:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
There was an unexpected error (type=Internal Server Error, status=500).
Error resolving template "login", template might not exist or might not be accessible by any of the configured Template Resolvers
However when I try localhost:8080/ it will successfully redirect to index.html as I specified in MvcConfig.java.
Here is my login.html code:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="utf-8" />
<title>k</title>
</head>
I paste my login.html in /src/main/resources/templates and /src/main/webapp/ and /src/main/webapp/templates it still didn't work!
OK, so it was a simple mistake in pom.xml.
<!--<resources>-->
<!--<resource>-->
<!--<directory>src/main/resources</directory>-->
<!--<includes>-->
<!--<include>*</include>-->
<!--</includes>-->
<!--<filtering>true</filtering>-->
<!--</resource>-->
<!--</resources>-->
After I commented out these (as you see) from the pom file it worked perfectly.At least the above codes might be useful to someone else.

Spring Boot and Spring Security not honoring configureGlobal

I created a simple SpringBoot app and added spring security. When I login it is only accepting the default password it is generating.
It won't let me login using the username/password I have configured in WebSecurityConfigurerAdapter.
Here is my code. SsFirstApplication.java
#SpringBootApplication
#EnableAutoConfiguration
public class SsFirstApplication {
public static void main(String[] args) {
SpringApplication.run(SsFirstApplication.class, args);
}
}
My custom security config "SecurityConfig.java"
#Configuration
#EnableWebSecurity
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
public void configureGlobal(AuthenticationManagerBuilder authBuilder) throws Exception{
logInfo("configureGlobal");
authBuilder
.inMemoryAuthentication()
.withUser("user")
.password("password123");
//.roles("USER");
}
private void logInfo(String strToken){
for(int index=0;index<1;index++){
System.out.println("************************** "+strToken+" ****************************");
}
}
#Override
protected void configure(HttpSecurity http) throws Exception{
logInfo("configure");
http
.authorizeRequests()
.anyRequest().authenticated();
}
}
And finally the Web App Initializer "SecurityWebApplicationInitializer"
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer{
public SecurityWebApplicationInitializer(){
super(SecurityConfig.class);
}
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SecurityConfig.class };
}
}
When I start the SpringBoot app (I am using STS/Eclipse IDE) in the console it is generating and printing out the password for username "user".
When I try http://localhost:8080/admin it won't let me use the username/password I configured.
Here is my pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ss-first</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>demo.SsFirstApplication</start-class>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The configuration of Spring MVC and Spring security needs to be corrected. Following will be the configuration for you.
#SpringBootApplication
#Controller
public class App extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
#RequestMapping(value="/")
public String home() {
return "admin";
}
The SecurityConfig is more or less correct except you need to add the login url information as shown below.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin()
.loginPage("/login").failureUrl("/login?error").permitAll();
http.csrf().disable();
}
As menionted in the comments above SecurityWebApplicationInitializer is also not needed in your config.

Resources