Reputation: 639
I'm using Spring Security (Spring Boot app) with AngularJS, and I'm trying to allow/deny access to specific mappings based on user's granted authorities.
User.java
public class User implements UserDetails {
...
private String username;
private String password;
private boolean enabled;
private List<GrantedAuthority> grantedAuthorities;
public User(...) {...}
private class Permission implements GrantedAuthority {
String permission;
public Permission(String permission) {
this.permission = permission;
}
@Override
public String getAuthority() {
return permission;
}
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return grantedAuthorities;
}
...
}
Also, I have my own implementation of UserDetailsService
(method loadUserByUsername(String username)
) which populates user data with data from database.
Previously mentioned mappings are:
@RequestMapping("yes")
public void doesHaveAuthority() {yes();}
@PreAuthorize("hasAuthority('10001')")
private void yes() {}
@RequestMapping("no")
public void doesntHaveAuthority() {no();}
@PreAuthorize("hasAuthority('00000')")
private void no() {}
Where user does have authority "10001", but doesn't have authority "00000", and access to /yes
should be allowed, but access to /no
shouldn't. Unfortunately, both paths are allowed.
I have spring-security-config
as maven dependency as mentioned here.
My WEB-INF/web.xml
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/security.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
and WEB-INF/security.xml
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<context:component-scan base-package="com.mycompany.project" />
<global-method-security pre-post-annotations="enabled" />
</beans:beans>
So, to summarize: UserDetailsService implementation works (I can login with user credentials and logger prints granted authorities so I know they're there), but user can access both yes
and /no
paths when in reality he/she shouldn't be able to access /no
since he/she doesn't have authority (permission) "00000".
Maybe my xml config is not correct or isn't being read at all.
Thanks for your time
UPDATE As M. Deinum said in comments Spring Boot disregards web.xml and security.xml files. Solution was to modify SecurityConfiguration
which extends WebSecurityConfigurerAdapter
and add corresponding antMatchers with corresponding authorities.
Example:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and()
.authorizeRequests()
.antMatchers("/login.html", "/index.html", "/").permitAll()
.antMatchers("/yes").hasAuthority("10001")
.antMatchers("/no").hasAuthority("00000")
.anyRequest()
.authenticated().and()
.addFilterAfter(new CSRFHeaderFilter(), CsrfFilter.class)
.csrf().csrfTokenRepository(csrfTokenRepository());
}
Upvotes: 0
Views: 3214
Reputation: 639
User "We are Borg" asked me to post solution as an answer so here it goes:
Basically, since my app is Spring Boot app, it disregarded (ignored my .xml config files). Solution was quite simple: extend WebSecurityConfigurerAdapter
and override configure(HttpSecurity)
method. When overriding it, make sure that user has authority and/or permission to access path (antMatchers). It should look something like this:
SecurityConfiguration.java
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and()
.authorizeRequests()
.antMatchers("/login.html", "/index.html", "/").permitAll()
.antMatchers("/yes").hasAuthority("10001")
.antMatchers("/no").hasAuthority("00000")
.anyRequest().authenticated();
}
}
And you won't be needing @PreAuthorize
annotation anymore, nor will you need .xml config files (security.xml, web.xml, etc...)
Good luck ;)
Upvotes: 2