Bhawesh Ji
Bhawesh Ji

Reputation: 3

How to add security to spring based rest api's and static content

I have a web application + a set of rest APIs created with spring. It is essentially some html pages sending ajax requests to the rest server. The structure looks somewhat like this:

myWebapp -> src/main/webapp/public (public pages)
myWebapp -> src/main/webapp/resources (non - public pages, available only after login)

I need to secure some of the static content (non-public above) and the rest APIs (Preferably with LDAP, but that's not important). How do i configure the filters and/or spring security intercepts so that:

  1. Same credentials work for both static content and rest calls.
  2. User can login via a login page, and for further rest calls uses some token or something returned from server.

I have checked spring security schemes for rest API's and also found some resources on securing static content, but not able to figure out how to fit this together as above.

Upvotes: 0

Views: 1226

Answers (1)

Ali Dehghani
Ali Dehghani

Reputation: 48213

I guess you want to have two sets of resources. One of them is open for public access and available at, say, /public context and the other is protected and available at /protected.

First, you should create some Resource Handlers in your Web Configuration:

@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    // other stuffs

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/public/**").addResourceLocations("classpath:/public/");
        registry.addResourceHandler("/protected/**").addResourceLocations("classpath:/resources/");
    }
}

This way all the static contents in /public directory will be served at /public/** endpoint and /protected/** endpoint will serve files in the /resources directory.

Then you should configure Spring Security in order to protect /protected/** endpoint:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // other stuffs

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .antMatchers("/public/**").permitAll()
                    .antMatchers("/protected/**").authenticated()
                    .anyRequest().authenticated();
    }
}

Update For REST endpoints you can either use same the matchers or have finer grain control with Method Level Security. In order to enable method level security, add @EnableGlobalMethodSecurity(prePostEnabled = true) to your SecurityConfig. Then you can use PrePost annotations on hanlder methods, like following:

@RestController
@RequestMapping("/greet")
public class GreetingService {
    // it's a public rest endpoint
    @PreAuthorize("permitAll()")
    @RequestMapping("/public")
    public void doGreetToPublicUsers() {...}

    // it's a protected rest endpoint
    @PreAuthorize("isAuthenticated()")
    @RequestMapping("/protected")
    public void doGreetToProtectedUsers() {...}

    // it's a role protected rest endpoint
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @RequestMapping("/admin")
    public void justForAdmin() {...}
}

Upvotes: 1

Related Questions