PreAuthorize not working on Controller

此生再无相见时 提交于 2019-11-27 20:36:10

A common problem with using PrePost annotations on controllers is that Spring method security is based on Spring AOP, which is by default implemented with JDK proxies.

That means that it works fine on the service layer which is injected in controller layer as interfaces, but it is ignored on controller layer because controller generally do not implement interfaces.

The following is just my opinion:

  • prefered way: move the pre post annotation on service layer
  • if you cannot (or do not want to), try to have your controller implement an interface containing all the annotated methods
  • as a last way, use proxy-target-class=true
Eric Zürcher

You have to add @EnableGlobalMethodSecurity(prePostEnabled = true) in your WebSecurityConfig.

You can find it here: http://www.baeldung.com/spring-security-expressions-basic

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

I had a similar problem and the following solved it:

1) I had to make my method public (i.e. make your method home() public)

2) I have to use hasRole instead of hasAuthority

For making it working on controller layer. I had to put @EnableAspectJAutoProxy on my configuration class. Example :

@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy
@ComponentScan(basePackages = { "com.abc.fraud.ts.userservices.web.controller" })
public class WebConfig extends WebMvcConfigurerAdapter{

}

There are two different ways to use this, one is to prefix and one is not. And you maybe change @PreAuthorize("hasAuthority('ROLE_ADMIN')") to @PreAuthorize("hasAuthority('ADMIN')") will be ok.

next is @PreAuthorize source code.

private String defaultRolePrefix = "ROLE_";
public final boolean hasAuthority(String authority) {
    return hasAnyAuthority(authority);
}

public final boolean hasAnyAuthority(String... authorities) {
    return hasAnyAuthorityName(null, authorities);
}

public final boolean hasRole(String role) {
    return hasAnyRole(role);
}

public final boolean hasAnyRole(String... roles) {
    return hasAnyAuthorityName(defaultRolePrefix, roles);
}

If you have a xml context file for your security beans and a separate one for your web/servlet context, than you als need to add:

<security:global-method-security pre-post-annotations="enabled"/>

to your web-context.xml / servlet context. Its not enough to just add it in the security context xml.

Its not inherited in child contexts.

HTH

put @EnableGlobalMethodSecurity(prePostEnabled = true) into MvcConfig class (extends WebMvcConfigurerAdapter) instead of (extends WebSecurityConfigurerAdapter).

Like below example:-

@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MvcConfiguration extends WebMvcConfigurerAdapter {
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!