Diffrent way of implementation security ends with the same error - spring

I have implemented an application with combination Spring Boot and Angular 4. I put all Angular files under /resources/static directory:
static directory
Then I added to Spring Security classes:
#Configuration
#EnableWebMvc
#ComponentScan("com.inventory")
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/static/**")
.addResourceLocations("classpath:/resources/static/");
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index.html");
}
}
and:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordencoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated();
}
and it seem that everythings should work. Unfortunately whenever I run my app it throws exception:
There was an unexpected error (type=Internal Server Error, status=500).
Could not resolve view with name 'index.html' in servlet with name 'dispatcherServlet'.
Of course I tried diffrent solution like adding this:
#Controller
public class ViewController {
#RequestMapping(value = "/#/")
public String index() {
return "forward:/index.html";
}
#RequestMapping(value = "/")
public String home() {
return "forward:/index.html";
}
}
But nothing works. Does anyone has a clue what else can I do?

When using Spring boot normally you don't have to configure resource handler manually, spring boot will automatically load contents from the following loc:
/static
/public
/resources
/META-INF/resources
see spring boot guides on loading static contents

Related

Couldn't access jpg file under resources/static folder

I couldn't access the image under the resources/static folder. I'm using Spring Boot version 2.112.
I also tried adding spring.resources.static-locations in the properties file but still can't access the .jpg file from the resources/static/image folder. Any reason why?
#Configuration
public class WebConfiguration extends WebMvcConfigurationSupport {
#Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/", "classpath:/image/");
}
Well, you may try https://stackoverflow.com/a/66361120/15215155. Most of time is about spring boot default security configuration.
Edit: Little edit here since it would be too much for comments.
Tackling the problem from another angle. Is there any specific feature you need from WebMvcConfigurationSupport?? If not, why not trying WebSecurityConfigurer for the resources handlers and WebSecurityConfigurerAdapter for the security config?.
#Configuration
#EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/**", "/js/**")
.addResourceLocations("classpath:/static/", "classpath:/resources/static/");
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/static/images/");
}
}
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/image/**"").permitAll()
}
}

Spring boot RequestMapping URLs not protected when not in ResourceServerConfiguration class

I've started with the following file to config URLs and protected paths using Spring Security and OAuth2:
#EnableResourceServer
#RestController
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter
{
#RequestMapping("/publica")
public String publico() {
return "Pagina Publica";
}
#RequestMapping("/privada")
public String privada() {
return "Pagina Privada";
}
#RequestMapping("/admin")
public String admin() {
return "Pagina Administrador";
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/oauth/token", "/oauth/authorize**", "/publica").permitAll();
http
.requestMatchers().antMatchers("/privada")
.and().authorizeRequests()
.antMatchers("/privada").access("hasRole('USER')")
.and().requestMatchers().antMatchers("/admin")
.and().authorizeRequests()
.antMatchers("/admin").access("hasRole('ADMIN')");
}
}
This works fine. If I try to access /privada in postman it returns a 401.
However, for the app I'm planning to build from this I figured it would be better to organise URLs in their own controllers (e.g. FundsController, UsersController, ProductsController etc)
So, as a basic example from the above I'm moving the path mapping methods out into BasicController:
#RestController
public class BasicController
{
#RequestMapping("/publica")
public String publico() {
return "Pagina Publica";
}
#RequestMapping("/privada")
public String privada() {
return "Pagina Privada";
}
#RequestMapping("/admin")
public String admin() {
return "Pagina Administrador";
}
}
But leaving the security stuff in the ResourceServerConfiguration:
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter
{
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/oauth/token", "/oauth/authorize**", "/publica").permitAll();
http
.requestMatchers().antMatchers("/privada")
.and().authorizeRequests()
.antMatchers("/privada").access("hasRole('USER')")
.and().requestMatchers().antMatchers("/admin")
.and().authorizeRequests()
.antMatchers("/admin").access("hasRole('ADMIN')");
}
}
But now when I restart the app (in-memory access tokens destroyed) then go to /privada it returns Pagina Privada which is Spanish I think for "Private page" :) There was no access token required anyway, which is not what I wanted. It should return a 401 as it did before when it was all within the same class. Where have I gone wrong?
Add
#Configuration
#EnableWebSecurity
annotations to your ResourceServerConfiguration class and
extend WebSecurityConfigurerAdapter instead of ResourceServerConfigurerAdapter
You need to have below in the configure method you override
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/context"))
.antMatchers("/context/**").fullyAuthenticated();

Spring Security does not intercept requests

I have a legacy application in which I have added Spring Web MVC libraries in order to expose a new Rest API.
I am struggling integrating spring-security in order to intercept the incoming requests. I have set up a security configuration class
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
}
and a security application initializer
public class SecurityWebApplicationInitializer extends
AbstractSecurityWebApplicationInitializer {
}
following relevant guides.
Using debugger I verified that during initializing my configuration class is loaded. My problem is that my requests are not intercepted as expected.
Since you're already using Spring MVC, go to your class that initializes your application. If you're using Java Config, it most likely extends AbstractAnnotationConfigDispatcherServletInitializer.
Add your SecurityConfig to its "root config classes":
public class MySpringMmvcInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
...
#Override
protected abstract Class<?>[] getRootConfigClasses() {
return new Class[] { ..., SecurityConfig.class};
}
}
I think you forgot the #configuration annotation, try this
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
}

Spring Security OAuth2: multiple ResourceServerConfiguration not working

Spring boot version: 1.5.8.RELEASE
Spring cloud version: Edgware.RELEASE (using zuul)
Trying to configure multiple resources and, following this example in github, can't make it work.
My code is:
class ResourceServerConfigurationFactory
{
static ResourceServerConfiguration criarResourceServerConfiguration(String resourceId, int order,
HttpSecurityConfigurer configurer)
{
ResourceServerConfiguration resource = new ResourceServerConfiguration()
{
// Switch off the Spring Boot #Autowired configurers
public void setConfigurers(List<ResourceServerConfigurer> configurers)
{
super.setConfigurers(configurers);
}
};
resource.setConfigurers(Arrays.<ResourceServerConfigurer>asList(new ResourceServerConfigurerAdapter()
{
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception
{
resources.resourceId(resourceId);
}
#Override
public void configure(HttpSecurity http) throws Exception
{
configurer.configure(http);
}
}));
resource.setOrder(order);
return resource;
}
}
interface HttpSecurityConfigurer
{
public void configure(HttpSecurity http) throws Exception;
}
And my configuration:
#Configuration
public class OAuthResourceConfiguration
{
#Bean
protected ResourceServerConfiguration usuarioResources()
{
return ResourceServerConfigurationFactory.criarResourceServerConfiguration("usuario", -10,
http -> http.antMatcher("/user").authorizeRequests().anyRequest().permitAll());
}
#Bean
protected ResourceServerConfiguration funcaoResources()
{
return ResourceServerConfigurationFactory.criarResourceServerConfiguration("funcao", -20,
http -> http.antMatcher("/ws").authorizeRequests().anyRequest().permitAll());
}
}
Finally, the Spring boot application:
#SpringBootApplication
#EnableResourceServer
#EnableZuulProxy
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}
Facts:
Spring instantiates both ResourceServerConfiguration beans;
Only the bean with higher order works (/user endpoint is ok, /ws endpoint keeps asking authentication)
In spring log, I can see that only /user ant matcher is used. /ws gets completely ignored.
What's wrong?
The problem was related to the Factory class I created.
The combination of lambda + anonymous class created some kind of problem (that I was not able to understand) that screwed up things.
Declaring both Configurers as Beans in the #Configuration class resolved the problem.

Global method security in Spring Boot

I'm having some issues when trying to enable the global method security in a Spring Boot application.
More or less I've this configuration:
#ComponentScan
#Configuration
#EnableAutoConfiguration
#EnableConfigurationProperties
public class Main extends SpringBootServletInitializer {
public static void main(String[] args) throws Exception {
SpringApplication app = new SpringApplication(Main.class);
app.setShowBanner(false);
ApplicationContext context = app.run(args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Main.class);
}
}
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, proxyTargetClass = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
...
}
#Override
protected void configure(HttpSecurity http) throws Exception {
...
}
}
#Controller
public class SampleController {
#RequestMapping("/api/hello")
#ResponseBody
String hello() {
return "Hello!";
}
#Secured(SecurityGrant.WRITE_PROJECT)
#RequestMapping("/api/bye")
#ResponseBody
String bye() {
return "Bye!";
}
}
The #Secure annotations are working OK at services, but not in controllers, so as I read here (http://docs.spring.io/spring-security/site/faq/faq.html#faq-method-security-in-web-context) I think is because method security is only configured in the root application context and not in the one for the servlet.
However, I can't find the way to set this via Java Configuration, instead of using a web.xml file.
Any ideas?
Update:
As pointed in the comments, methods should be public to be proxied.
The controller methods need to be public in order to be proxied for #Secured. Just doing that should fix it.
In XML you would have to define a second global-method-security in the servlet-context.xml file. This is because there are two contexts, the root context and the web context and security needs to be configured in each separately.
In Java config, try to create a separate web configuration class, and mark it with #EnableWebMvc:
#Configuration
#EnableWebMvc
#EnableGlobalMethodSecurity(securedEnabled = true, proxyTargetClass = true)
public class WebConfig {
...
}

Resources