Spring Security, Method Security annotation (@Secured ) is not working (java config)
I am trying to set up a method security annotation using @Secured("ADMIN") (without any XML, only java config, Spring Boot). But access via roles does not work.
Security Config:
@Configuration
@EnableWebSecurity
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{
.....
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/**").fullyAuthenticated().and()
.addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
.....
}
I want restrict access to the method of the controller:
@RestController
@RequestMapping("/api/groups")
public class GroupController {
@Autowired
private GroupService groupService;
@Secured("ADMIN")
@RequestMapping
public List<Group> list() {
return groupService.findAll();
}
}
Restrict access by the url is working, with:
.antMatchers("/api/**").hasAuthority("ADMIN")
Maybe I forgot to specify that I want restrict by roles?
UPD:
By the rules, At what layer must be @PreAuthorize("hasRole('ADMIN')")
in Controller layer or in Service layer?
java spring security spring-security spring-boot
add a comment |
I am trying to set up a method security annotation using @Secured("ADMIN") (without any XML, only java config, Spring Boot). But access via roles does not work.
Security Config:
@Configuration
@EnableWebSecurity
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{
.....
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/**").fullyAuthenticated().and()
.addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
.....
}
I want restrict access to the method of the controller:
@RestController
@RequestMapping("/api/groups")
public class GroupController {
@Autowired
private GroupService groupService;
@Secured("ADMIN")
@RequestMapping
public List<Group> list() {
return groupService.findAll();
}
}
Restrict access by the url is working, with:
.antMatchers("/api/**").hasAuthority("ADMIN")
Maybe I forgot to specify that I want restrict by roles?
UPD:
By the rules, At what layer must be @PreAuthorize("hasRole('ADMIN')")
in Controller layer or in Service layer?
java spring security spring-security spring-boot
What does not work ? Is the browsers not trying to authenticate you ? Does it ignore the credentials you provide ? By the way: you should also post where you map your user to the admin group, perhaps this is the problematic area.
– Marged
Jul 2 '15 at 14:10
1
The authentication working correctly, but any user with any role have access to "/api/groups"
– silverhawk
Jul 2 '15 at 14:13
1
Where are you setting the ROLE 'ADMIN', can you show me that??
– We are Borg
Jul 2 '15 at 14:16
Despite the fact that role is defined correctly:org.springframework.security.authentication.UsernamePasswordAuthenticationToken: Principal: SecurityUser; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ADMIN
– silverhawk
Jul 2 '15 at 14:17
1
here you see that authority was actuallyADMIN
and notROLE_ADMIN
. Because RoleVoter checks authorities with starting withROLE_
it can't find your authority (which isADMIN
) and thus abstains
– pls
Jul 2 '18 at 11:53
add a comment |
I am trying to set up a method security annotation using @Secured("ADMIN") (without any XML, only java config, Spring Boot). But access via roles does not work.
Security Config:
@Configuration
@EnableWebSecurity
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{
.....
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/**").fullyAuthenticated().and()
.addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
.....
}
I want restrict access to the method of the controller:
@RestController
@RequestMapping("/api/groups")
public class GroupController {
@Autowired
private GroupService groupService;
@Secured("ADMIN")
@RequestMapping
public List<Group> list() {
return groupService.findAll();
}
}
Restrict access by the url is working, with:
.antMatchers("/api/**").hasAuthority("ADMIN")
Maybe I forgot to specify that I want restrict by roles?
UPD:
By the rules, At what layer must be @PreAuthorize("hasRole('ADMIN')")
in Controller layer or in Service layer?
java spring security spring-security spring-boot
I am trying to set up a method security annotation using @Secured("ADMIN") (without any XML, only java config, Spring Boot). But access via roles does not work.
Security Config:
@Configuration
@EnableWebSecurity
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{
.....
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/**").fullyAuthenticated().and()
.addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
.....
}
I want restrict access to the method of the controller:
@RestController
@RequestMapping("/api/groups")
public class GroupController {
@Autowired
private GroupService groupService;
@Secured("ADMIN")
@RequestMapping
public List<Group> list() {
return groupService.findAll();
}
}
Restrict access by the url is working, with:
.antMatchers("/api/**").hasAuthority("ADMIN")
Maybe I forgot to specify that I want restrict by roles?
UPD:
By the rules, At what layer must be @PreAuthorize("hasRole('ADMIN')")
in Controller layer or in Service layer?
java spring security spring-security spring-boot
java spring security spring-security spring-boot
edited Jul 7 '15 at 9:40
silverhawk
asked Jul 2 '15 at 14:06
silverhawksilverhawk
1091111
1091111
What does not work ? Is the browsers not trying to authenticate you ? Does it ignore the credentials you provide ? By the way: you should also post where you map your user to the admin group, perhaps this is the problematic area.
– Marged
Jul 2 '15 at 14:10
1
The authentication working correctly, but any user with any role have access to "/api/groups"
– silverhawk
Jul 2 '15 at 14:13
1
Where are you setting the ROLE 'ADMIN', can you show me that??
– We are Borg
Jul 2 '15 at 14:16
Despite the fact that role is defined correctly:org.springframework.security.authentication.UsernamePasswordAuthenticationToken: Principal: SecurityUser; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ADMIN
– silverhawk
Jul 2 '15 at 14:17
1
here you see that authority was actuallyADMIN
and notROLE_ADMIN
. Because RoleVoter checks authorities with starting withROLE_
it can't find your authority (which isADMIN
) and thus abstains
– pls
Jul 2 '18 at 11:53
add a comment |
What does not work ? Is the browsers not trying to authenticate you ? Does it ignore the credentials you provide ? By the way: you should also post where you map your user to the admin group, perhaps this is the problematic area.
– Marged
Jul 2 '15 at 14:10
1
The authentication working correctly, but any user with any role have access to "/api/groups"
– silverhawk
Jul 2 '15 at 14:13
1
Where are you setting the ROLE 'ADMIN', can you show me that??
– We are Borg
Jul 2 '15 at 14:16
Despite the fact that role is defined correctly:org.springframework.security.authentication.UsernamePasswordAuthenticationToken: Principal: SecurityUser; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ADMIN
– silverhawk
Jul 2 '15 at 14:17
1
here you see that authority was actuallyADMIN
and notROLE_ADMIN
. Because RoleVoter checks authorities with starting withROLE_
it can't find your authority (which isADMIN
) and thus abstains
– pls
Jul 2 '18 at 11:53
What does not work ? Is the browsers not trying to authenticate you ? Does it ignore the credentials you provide ? By the way: you should also post where you map your user to the admin group, perhaps this is the problematic area.
– Marged
Jul 2 '15 at 14:10
What does not work ? Is the browsers not trying to authenticate you ? Does it ignore the credentials you provide ? By the way: you should also post where you map your user to the admin group, perhaps this is the problematic area.
– Marged
Jul 2 '15 at 14:10
1
1
The authentication working correctly, but any user with any role have access to "/api/groups"
– silverhawk
Jul 2 '15 at 14:13
The authentication working correctly, but any user with any role have access to "/api/groups"
– silverhawk
Jul 2 '15 at 14:13
1
1
Where are you setting the ROLE 'ADMIN', can you show me that??
– We are Borg
Jul 2 '15 at 14:16
Where are you setting the ROLE 'ADMIN', can you show me that??
– We are Borg
Jul 2 '15 at 14:16
Despite the fact that role is defined correctly:
org.springframework.security.authentication.UsernamePasswordAuthenticationToken: Principal: SecurityUser; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ADMIN
– silverhawk
Jul 2 '15 at 14:17
Despite the fact that role is defined correctly:
org.springframework.security.authentication.UsernamePasswordAuthenticationToken: Principal: SecurityUser; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ADMIN
– silverhawk
Jul 2 '15 at 14:17
1
1
here you see that authority was actually
ADMIN
and not ROLE_ADMIN
. Because RoleVoter checks authorities with starting with ROLE_
it can't find your authority (which is ADMIN
) and thus abstains– pls
Jul 2 '18 at 11:53
here you see that authority was actually
ADMIN
and not ROLE_ADMIN
. Because RoleVoter checks authorities with starting with ROLE_
it can't find your authority (which is ADMIN
) and thus abstains– pls
Jul 2 '18 at 11:53
add a comment |
7 Answers
7
active
oldest
votes
Kindly add this
@EnableGlobalMethodSecurity(securedEnabled = true)
This element is used to enable annotation-based security in your application (by setting the appropriate attributes on the element), and also to group together security pointcut declarations which will be applied across your entire application context specifically for @Secured
.
Hence your code should look like this
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{..
made the edit for specifically securedEnabled = true
– Mudassar
Jul 2 '15 at 14:37
i am try this, but this does not work correctly, ie spring response "Access denied"
– silverhawk
Jul 2 '15 at 15:25
Let's do some analysis, any surviving reason of adding @RequestMapping below Secured("ADMIN")
– Mudassar
Jul 2 '15 at 15:37
Any progress? Did you try removing that @RequestMapping below @Secured("ADMIN")
– Mudassar
Jul 2 '15 at 16:54
Kindly let me know if you made any progress or if the solution is fixed with the help of the proposed solution then kindly close the question by accepting the answer
– Mudassar
Jul 3 '15 at 14:35
|
show 4 more comments
There may be many reasons for which method security on a controller does not work.
First because it is never cited as example in Spring Security manual ... joking but it may be tricky to take Spring tools where they do not want to go.
More seriously, you should enable method security as already said by @Mudassar. The manual says :
We can enable annotation-based security using the @EnableGlobalMethodSecurity
annotation on any @Configuration
instance. For example, the following would enable Spring Security’s @Secured
annotation.
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
// ...
}
Note that Mudassar's answer is correct till here.
But method security is based on AOP, which by default uses JDK proxying on interfaces. That's the reason why all examples applies method security on the service layer, because the service classes are normally injected in controllers as interfaces.
You can of course use it on controller layer, but :
- either all your controllers implement interfaces for you all
@Secured
annotated methods - or you must switch to class proxying
The rule that I try to follow is :
- if I want to secure an URL, I stick to HTTPSecurity
- if I need to allow finer grained access, I add security at service layer
add a comment |
I know this thread is quite old and my answer alludes to portions of the answers by various people in this thread; but here is a list combined list of pitfalls and answers:
- When using @Secured, and the role name is (e.g.) ADMIN; this means an annotation of @Secured("ROLE_ADMIN").
- WebSecurityConfigurerAdapter must have @EnableGlobalMethodSecurity(securedEnabled = true)
- As with most Spring related proxies, make sure that the class and the secured methods are not in any way final. For Kotlin this means "open" every method as well as the class.
- When the class and its methods are virtual ("open"), then there is no implied need for an interface.
Here is part of a working Kotlin example:
@RestController
@RequestMapping("api/v1")
open class DiagnosticsController {
@Autowired
lateinit var systemDao : SystemDao
@RequestMapping("ping", method = arrayOf(RequestMethod.GET))
@Secured("ROLE_ADMIN")
open fun ping(request : HttpServletRequest, response: HttpServletResponse) : String { ...
}
and
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
open class WebSecurityConfig : WebSecurityConfigurerAdapter() {
Regards
add a comment |
This issue was solved.
I add @EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{
}
And in controller i changed @Secured("ADMIN")
to @PreAuthorize("hasRole('ADMIN')")
add a comment |
You need to use @secured(ROLE_ADMIN) instead of @secured(ADMIN). You are required to write "ROLE_" infront of your role name. Please find the example mentioned below which is making sure only a user with Admin role can access list() method.
@RestController
@RequestMapping("/api/groups")
public class GroupController {
@Autowired
private GroupService groupService;
@Secured("ROLE_ADMIN")
@RequestMapping
public List<Group> list() {
return groupService.findAll();
}
}
add a comment |
Maybe you should register your AppSecurityConfiguration to same context as WebMvcConfig (that extends WebMvcConfigurerAdapter).
AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();
mvcContext.register(WebMvcConfig.class, SecurityConfig.class);
add a comment |
I want to share my decision, may be it will be helpful.
Used spring mvc + spring security, version 4.2.9.RELEASE
For example, i have a Service with method annotated @Secured
@Secured("ACTION_USER_LIST_VIEW")
List<User> getUsersList();
But, it didn't work, because GlobalMethodSecurityConfiguration has inside method.
protected AccessDecisionManager accessDecisionManager()
in which initialized the new RoleVoter()
with default rolePrefix = "ROLE_";
(this makes it impossible to use beans to set your rolePrefix) that give to us not working annotations, because RoleVoter expects annotation value which starts with 'ROLE_'
For resolving this problem i override GlobalMethodSecurityConfiguration like this
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
@Override
protected AccessDecisionManager accessDecisionManager() {
List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<>();
ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice();
expressionAdvice.setExpressionHandler(getExpressionHandler());
decisionVoters.add(getRoleVoter());
decisionVoters.add(new AuthenticatedVoter());
return new AffirmativeBased(decisionVoters);
}
private RoleVoter getRoleVoter() {
RoleVoter e = new RoleVoter();
e.setRolePrefix("");
return e;
}
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f31186826%2fspring-security-method-security-annotation-secured-is-not-working-java-con%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
7 Answers
7
active
oldest
votes
7 Answers
7
active
oldest
votes
active
oldest
votes
active
oldest
votes
Kindly add this
@EnableGlobalMethodSecurity(securedEnabled = true)
This element is used to enable annotation-based security in your application (by setting the appropriate attributes on the element), and also to group together security pointcut declarations which will be applied across your entire application context specifically for @Secured
.
Hence your code should look like this
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{..
made the edit for specifically securedEnabled = true
– Mudassar
Jul 2 '15 at 14:37
i am try this, but this does not work correctly, ie spring response "Access denied"
– silverhawk
Jul 2 '15 at 15:25
Let's do some analysis, any surviving reason of adding @RequestMapping below Secured("ADMIN")
– Mudassar
Jul 2 '15 at 15:37
Any progress? Did you try removing that @RequestMapping below @Secured("ADMIN")
– Mudassar
Jul 2 '15 at 16:54
Kindly let me know if you made any progress or if the solution is fixed with the help of the proposed solution then kindly close the question by accepting the answer
– Mudassar
Jul 3 '15 at 14:35
|
show 4 more comments
Kindly add this
@EnableGlobalMethodSecurity(securedEnabled = true)
This element is used to enable annotation-based security in your application (by setting the appropriate attributes on the element), and also to group together security pointcut declarations which will be applied across your entire application context specifically for @Secured
.
Hence your code should look like this
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{..
made the edit for specifically securedEnabled = true
– Mudassar
Jul 2 '15 at 14:37
i am try this, but this does not work correctly, ie spring response "Access denied"
– silverhawk
Jul 2 '15 at 15:25
Let's do some analysis, any surviving reason of adding @RequestMapping below Secured("ADMIN")
– Mudassar
Jul 2 '15 at 15:37
Any progress? Did you try removing that @RequestMapping below @Secured("ADMIN")
– Mudassar
Jul 2 '15 at 16:54
Kindly let me know if you made any progress or if the solution is fixed with the help of the proposed solution then kindly close the question by accepting the answer
– Mudassar
Jul 3 '15 at 14:35
|
show 4 more comments
Kindly add this
@EnableGlobalMethodSecurity(securedEnabled = true)
This element is used to enable annotation-based security in your application (by setting the appropriate attributes on the element), and also to group together security pointcut declarations which will be applied across your entire application context specifically for @Secured
.
Hence your code should look like this
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{..
Kindly add this
@EnableGlobalMethodSecurity(securedEnabled = true)
This element is used to enable annotation-based security in your application (by setting the appropriate attributes on the element), and also to group together security pointcut declarations which will be applied across your entire application context specifically for @Secured
.
Hence your code should look like this
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{..
edited Oct 19 '17 at 4:12
answered Jul 2 '15 at 14:31
MudassarMudassar
1,967917
1,967917
made the edit for specifically securedEnabled = true
– Mudassar
Jul 2 '15 at 14:37
i am try this, but this does not work correctly, ie spring response "Access denied"
– silverhawk
Jul 2 '15 at 15:25
Let's do some analysis, any surviving reason of adding @RequestMapping below Secured("ADMIN")
– Mudassar
Jul 2 '15 at 15:37
Any progress? Did you try removing that @RequestMapping below @Secured("ADMIN")
– Mudassar
Jul 2 '15 at 16:54
Kindly let me know if you made any progress or if the solution is fixed with the help of the proposed solution then kindly close the question by accepting the answer
– Mudassar
Jul 3 '15 at 14:35
|
show 4 more comments
made the edit for specifically securedEnabled = true
– Mudassar
Jul 2 '15 at 14:37
i am try this, but this does not work correctly, ie spring response "Access denied"
– silverhawk
Jul 2 '15 at 15:25
Let's do some analysis, any surviving reason of adding @RequestMapping below Secured("ADMIN")
– Mudassar
Jul 2 '15 at 15:37
Any progress? Did you try removing that @RequestMapping below @Secured("ADMIN")
– Mudassar
Jul 2 '15 at 16:54
Kindly let me know if you made any progress or if the solution is fixed with the help of the proposed solution then kindly close the question by accepting the answer
– Mudassar
Jul 3 '15 at 14:35
made the edit for specifically securedEnabled = true
– Mudassar
Jul 2 '15 at 14:37
made the edit for specifically securedEnabled = true
– Mudassar
Jul 2 '15 at 14:37
i am try this, but this does not work correctly, ie spring response "Access denied"
– silverhawk
Jul 2 '15 at 15:25
i am try this, but this does not work correctly, ie spring response "Access denied"
– silverhawk
Jul 2 '15 at 15:25
Let's do some analysis, any surviving reason of adding @RequestMapping below Secured("ADMIN")
– Mudassar
Jul 2 '15 at 15:37
Let's do some analysis, any surviving reason of adding @RequestMapping below Secured("ADMIN")
– Mudassar
Jul 2 '15 at 15:37
Any progress? Did you try removing that @RequestMapping below @Secured("ADMIN")
– Mudassar
Jul 2 '15 at 16:54
Any progress? Did you try removing that @RequestMapping below @Secured("ADMIN")
– Mudassar
Jul 2 '15 at 16:54
Kindly let me know if you made any progress or if the solution is fixed with the help of the proposed solution then kindly close the question by accepting the answer
– Mudassar
Jul 3 '15 at 14:35
Kindly let me know if you made any progress or if the solution is fixed with the help of the proposed solution then kindly close the question by accepting the answer
– Mudassar
Jul 3 '15 at 14:35
|
show 4 more comments
There may be many reasons for which method security on a controller does not work.
First because it is never cited as example in Spring Security manual ... joking but it may be tricky to take Spring tools where they do not want to go.
More seriously, you should enable method security as already said by @Mudassar. The manual says :
We can enable annotation-based security using the @EnableGlobalMethodSecurity
annotation on any @Configuration
instance. For example, the following would enable Spring Security’s @Secured
annotation.
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
// ...
}
Note that Mudassar's answer is correct till here.
But method security is based on AOP, which by default uses JDK proxying on interfaces. That's the reason why all examples applies method security on the service layer, because the service classes are normally injected in controllers as interfaces.
You can of course use it on controller layer, but :
- either all your controllers implement interfaces for you all
@Secured
annotated methods - or you must switch to class proxying
The rule that I try to follow is :
- if I want to secure an URL, I stick to HTTPSecurity
- if I need to allow finer grained access, I add security at service layer
add a comment |
There may be many reasons for which method security on a controller does not work.
First because it is never cited as example in Spring Security manual ... joking but it may be tricky to take Spring tools where they do not want to go.
More seriously, you should enable method security as already said by @Mudassar. The manual says :
We can enable annotation-based security using the @EnableGlobalMethodSecurity
annotation on any @Configuration
instance. For example, the following would enable Spring Security’s @Secured
annotation.
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
// ...
}
Note that Mudassar's answer is correct till here.
But method security is based on AOP, which by default uses JDK proxying on interfaces. That's the reason why all examples applies method security on the service layer, because the service classes are normally injected in controllers as interfaces.
You can of course use it on controller layer, but :
- either all your controllers implement interfaces for you all
@Secured
annotated methods - or you must switch to class proxying
The rule that I try to follow is :
- if I want to secure an URL, I stick to HTTPSecurity
- if I need to allow finer grained access, I add security at service layer
add a comment |
There may be many reasons for which method security on a controller does not work.
First because it is never cited as example in Spring Security manual ... joking but it may be tricky to take Spring tools where they do not want to go.
More seriously, you should enable method security as already said by @Mudassar. The manual says :
We can enable annotation-based security using the @EnableGlobalMethodSecurity
annotation on any @Configuration
instance. For example, the following would enable Spring Security’s @Secured
annotation.
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
// ...
}
Note that Mudassar's answer is correct till here.
But method security is based on AOP, which by default uses JDK proxying on interfaces. That's the reason why all examples applies method security on the service layer, because the service classes are normally injected in controllers as interfaces.
You can of course use it on controller layer, but :
- either all your controllers implement interfaces for you all
@Secured
annotated methods - or you must switch to class proxying
The rule that I try to follow is :
- if I want to secure an URL, I stick to HTTPSecurity
- if I need to allow finer grained access, I add security at service layer
There may be many reasons for which method security on a controller does not work.
First because it is never cited as example in Spring Security manual ... joking but it may be tricky to take Spring tools where they do not want to go.
More seriously, you should enable method security as already said by @Mudassar. The manual says :
We can enable annotation-based security using the @EnableGlobalMethodSecurity
annotation on any @Configuration
instance. For example, the following would enable Spring Security’s @Secured
annotation.
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
// ...
}
Note that Mudassar's answer is correct till here.
But method security is based on AOP, which by default uses JDK proxying on interfaces. That's the reason why all examples applies method security on the service layer, because the service classes are normally injected in controllers as interfaces.
You can of course use it on controller layer, but :
- either all your controllers implement interfaces for you all
@Secured
annotated methods - or you must switch to class proxying
The rule that I try to follow is :
- if I want to secure an URL, I stick to HTTPSecurity
- if I need to allow finer grained access, I add security at service layer
answered Jul 2 '15 at 14:49
Serge BallestaSerge Ballesta
80.8k961133
80.8k961133
add a comment |
add a comment |
I know this thread is quite old and my answer alludes to portions of the answers by various people in this thread; but here is a list combined list of pitfalls and answers:
- When using @Secured, and the role name is (e.g.) ADMIN; this means an annotation of @Secured("ROLE_ADMIN").
- WebSecurityConfigurerAdapter must have @EnableGlobalMethodSecurity(securedEnabled = true)
- As with most Spring related proxies, make sure that the class and the secured methods are not in any way final. For Kotlin this means "open" every method as well as the class.
- When the class and its methods are virtual ("open"), then there is no implied need for an interface.
Here is part of a working Kotlin example:
@RestController
@RequestMapping("api/v1")
open class DiagnosticsController {
@Autowired
lateinit var systemDao : SystemDao
@RequestMapping("ping", method = arrayOf(RequestMethod.GET))
@Secured("ROLE_ADMIN")
open fun ping(request : HttpServletRequest, response: HttpServletResponse) : String { ...
}
and
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
open class WebSecurityConfig : WebSecurityConfigurerAdapter() {
Regards
add a comment |
I know this thread is quite old and my answer alludes to portions of the answers by various people in this thread; but here is a list combined list of pitfalls and answers:
- When using @Secured, and the role name is (e.g.) ADMIN; this means an annotation of @Secured("ROLE_ADMIN").
- WebSecurityConfigurerAdapter must have @EnableGlobalMethodSecurity(securedEnabled = true)
- As with most Spring related proxies, make sure that the class and the secured methods are not in any way final. For Kotlin this means "open" every method as well as the class.
- When the class and its methods are virtual ("open"), then there is no implied need for an interface.
Here is part of a working Kotlin example:
@RestController
@RequestMapping("api/v1")
open class DiagnosticsController {
@Autowired
lateinit var systemDao : SystemDao
@RequestMapping("ping", method = arrayOf(RequestMethod.GET))
@Secured("ROLE_ADMIN")
open fun ping(request : HttpServletRequest, response: HttpServletResponse) : String { ...
}
and
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
open class WebSecurityConfig : WebSecurityConfigurerAdapter() {
Regards
add a comment |
I know this thread is quite old and my answer alludes to portions of the answers by various people in this thread; but here is a list combined list of pitfalls and answers:
- When using @Secured, and the role name is (e.g.) ADMIN; this means an annotation of @Secured("ROLE_ADMIN").
- WebSecurityConfigurerAdapter must have @EnableGlobalMethodSecurity(securedEnabled = true)
- As with most Spring related proxies, make sure that the class and the secured methods are not in any way final. For Kotlin this means "open" every method as well as the class.
- When the class and its methods are virtual ("open"), then there is no implied need for an interface.
Here is part of a working Kotlin example:
@RestController
@RequestMapping("api/v1")
open class DiagnosticsController {
@Autowired
lateinit var systemDao : SystemDao
@RequestMapping("ping", method = arrayOf(RequestMethod.GET))
@Secured("ROLE_ADMIN")
open fun ping(request : HttpServletRequest, response: HttpServletResponse) : String { ...
}
and
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
open class WebSecurityConfig : WebSecurityConfigurerAdapter() {
Regards
I know this thread is quite old and my answer alludes to portions of the answers by various people in this thread; but here is a list combined list of pitfalls and answers:
- When using @Secured, and the role name is (e.g.) ADMIN; this means an annotation of @Secured("ROLE_ADMIN").
- WebSecurityConfigurerAdapter must have @EnableGlobalMethodSecurity(securedEnabled = true)
- As with most Spring related proxies, make sure that the class and the secured methods are not in any way final. For Kotlin this means "open" every method as well as the class.
- When the class and its methods are virtual ("open"), then there is no implied need for an interface.
Here is part of a working Kotlin example:
@RestController
@RequestMapping("api/v1")
open class DiagnosticsController {
@Autowired
lateinit var systemDao : SystemDao
@RequestMapping("ping", method = arrayOf(RequestMethod.GET))
@Secured("ROLE_ADMIN")
open fun ping(request : HttpServletRequest, response: HttpServletResponse) : String { ...
}
and
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
open class WebSecurityConfig : WebSecurityConfigurerAdapter() {
Regards
edited Oct 10 '16 at 16:54
answered Oct 10 '16 at 16:48
user1210708user1210708
34838
34838
add a comment |
add a comment |
This issue was solved.
I add @EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{
}
And in controller i changed @Secured("ADMIN")
to @PreAuthorize("hasRole('ADMIN')")
add a comment |
This issue was solved.
I add @EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{
}
And in controller i changed @Secured("ADMIN")
to @PreAuthorize("hasRole('ADMIN')")
add a comment |
This issue was solved.
I add @EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{
}
And in controller i changed @Secured("ADMIN")
to @PreAuthorize("hasRole('ADMIN')")
This issue was solved.
I add @EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{
}
And in controller i changed @Secured("ADMIN")
to @PreAuthorize("hasRole('ADMIN')")
answered Jul 7 '15 at 9:40
silverhawksilverhawk
1091111
1091111
add a comment |
add a comment |
You need to use @secured(ROLE_ADMIN) instead of @secured(ADMIN). You are required to write "ROLE_" infront of your role name. Please find the example mentioned below which is making sure only a user with Admin role can access list() method.
@RestController
@RequestMapping("/api/groups")
public class GroupController {
@Autowired
private GroupService groupService;
@Secured("ROLE_ADMIN")
@RequestMapping
public List<Group> list() {
return groupService.findAll();
}
}
add a comment |
You need to use @secured(ROLE_ADMIN) instead of @secured(ADMIN). You are required to write "ROLE_" infront of your role name. Please find the example mentioned below which is making sure only a user with Admin role can access list() method.
@RestController
@RequestMapping("/api/groups")
public class GroupController {
@Autowired
private GroupService groupService;
@Secured("ROLE_ADMIN")
@RequestMapping
public List<Group> list() {
return groupService.findAll();
}
}
add a comment |
You need to use @secured(ROLE_ADMIN) instead of @secured(ADMIN). You are required to write "ROLE_" infront of your role name. Please find the example mentioned below which is making sure only a user with Admin role can access list() method.
@RestController
@RequestMapping("/api/groups")
public class GroupController {
@Autowired
private GroupService groupService;
@Secured("ROLE_ADMIN")
@RequestMapping
public List<Group> list() {
return groupService.findAll();
}
}
You need to use @secured(ROLE_ADMIN) instead of @secured(ADMIN). You are required to write "ROLE_" infront of your role name. Please find the example mentioned below which is making sure only a user with Admin role can access list() method.
@RestController
@RequestMapping("/api/groups")
public class GroupController {
@Autowired
private GroupService groupService;
@Secured("ROLE_ADMIN")
@RequestMapping
public List<Group> list() {
return groupService.findAll();
}
}
answered Mar 10 '17 at 5:55
Sadiq AliSadiq Ali
7121617
7121617
add a comment |
add a comment |
Maybe you should register your AppSecurityConfiguration to same context as WebMvcConfig (that extends WebMvcConfigurerAdapter).
AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();
mvcContext.register(WebMvcConfig.class, SecurityConfig.class);
add a comment |
Maybe you should register your AppSecurityConfiguration to same context as WebMvcConfig (that extends WebMvcConfigurerAdapter).
AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();
mvcContext.register(WebMvcConfig.class, SecurityConfig.class);
add a comment |
Maybe you should register your AppSecurityConfiguration to same context as WebMvcConfig (that extends WebMvcConfigurerAdapter).
AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();
mvcContext.register(WebMvcConfig.class, SecurityConfig.class);
Maybe you should register your AppSecurityConfiguration to same context as WebMvcConfig (that extends WebMvcConfigurerAdapter).
AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();
mvcContext.register(WebMvcConfig.class, SecurityConfig.class);
answered May 3 '16 at 8:16
digz6666digz6666
1,4792232
1,4792232
add a comment |
add a comment |
I want to share my decision, may be it will be helpful.
Used spring mvc + spring security, version 4.2.9.RELEASE
For example, i have a Service with method annotated @Secured
@Secured("ACTION_USER_LIST_VIEW")
List<User> getUsersList();
But, it didn't work, because GlobalMethodSecurityConfiguration has inside method.
protected AccessDecisionManager accessDecisionManager()
in which initialized the new RoleVoter()
with default rolePrefix = "ROLE_";
(this makes it impossible to use beans to set your rolePrefix) that give to us not working annotations, because RoleVoter expects annotation value which starts with 'ROLE_'
For resolving this problem i override GlobalMethodSecurityConfiguration like this
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
@Override
protected AccessDecisionManager accessDecisionManager() {
List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<>();
ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice();
expressionAdvice.setExpressionHandler(getExpressionHandler());
decisionVoters.add(getRoleVoter());
decisionVoters.add(new AuthenticatedVoter());
return new AffirmativeBased(decisionVoters);
}
private RoleVoter getRoleVoter() {
RoleVoter e = new RoleVoter();
e.setRolePrefix("");
return e;
}
}
add a comment |
I want to share my decision, may be it will be helpful.
Used spring mvc + spring security, version 4.2.9.RELEASE
For example, i have a Service with method annotated @Secured
@Secured("ACTION_USER_LIST_VIEW")
List<User> getUsersList();
But, it didn't work, because GlobalMethodSecurityConfiguration has inside method.
protected AccessDecisionManager accessDecisionManager()
in which initialized the new RoleVoter()
with default rolePrefix = "ROLE_";
(this makes it impossible to use beans to set your rolePrefix) that give to us not working annotations, because RoleVoter expects annotation value which starts with 'ROLE_'
For resolving this problem i override GlobalMethodSecurityConfiguration like this
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
@Override
protected AccessDecisionManager accessDecisionManager() {
List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<>();
ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice();
expressionAdvice.setExpressionHandler(getExpressionHandler());
decisionVoters.add(getRoleVoter());
decisionVoters.add(new AuthenticatedVoter());
return new AffirmativeBased(decisionVoters);
}
private RoleVoter getRoleVoter() {
RoleVoter e = new RoleVoter();
e.setRolePrefix("");
return e;
}
}
add a comment |
I want to share my decision, may be it will be helpful.
Used spring mvc + spring security, version 4.2.9.RELEASE
For example, i have a Service with method annotated @Secured
@Secured("ACTION_USER_LIST_VIEW")
List<User> getUsersList();
But, it didn't work, because GlobalMethodSecurityConfiguration has inside method.
protected AccessDecisionManager accessDecisionManager()
in which initialized the new RoleVoter()
with default rolePrefix = "ROLE_";
(this makes it impossible to use beans to set your rolePrefix) that give to us not working annotations, because RoleVoter expects annotation value which starts with 'ROLE_'
For resolving this problem i override GlobalMethodSecurityConfiguration like this
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
@Override
protected AccessDecisionManager accessDecisionManager() {
List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<>();
ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice();
expressionAdvice.setExpressionHandler(getExpressionHandler());
decisionVoters.add(getRoleVoter());
decisionVoters.add(new AuthenticatedVoter());
return new AffirmativeBased(decisionVoters);
}
private RoleVoter getRoleVoter() {
RoleVoter e = new RoleVoter();
e.setRolePrefix("");
return e;
}
}
I want to share my decision, may be it will be helpful.
Used spring mvc + spring security, version 4.2.9.RELEASE
For example, i have a Service with method annotated @Secured
@Secured("ACTION_USER_LIST_VIEW")
List<User> getUsersList();
But, it didn't work, because GlobalMethodSecurityConfiguration has inside method.
protected AccessDecisionManager accessDecisionManager()
in which initialized the new RoleVoter()
with default rolePrefix = "ROLE_";
(this makes it impossible to use beans to set your rolePrefix) that give to us not working annotations, because RoleVoter expects annotation value which starts with 'ROLE_'
For resolving this problem i override GlobalMethodSecurityConfiguration like this
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
@Override
protected AccessDecisionManager accessDecisionManager() {
List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<>();
ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice();
expressionAdvice.setExpressionHandler(getExpressionHandler());
decisionVoters.add(getRoleVoter());
decisionVoters.add(new AuthenticatedVoter());
return new AffirmativeBased(decisionVoters);
}
private RoleVoter getRoleVoter() {
RoleVoter e = new RoleVoter();
e.setRolePrefix("");
return e;
}
}
edited Nov 16 '18 at 22:43
answered Nov 16 '18 at 0:20
IgorIgor
13117
13117
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f31186826%2fspring-security-method-security-annotation-secured-is-not-working-java-con%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What does not work ? Is the browsers not trying to authenticate you ? Does it ignore the credentials you provide ? By the way: you should also post where you map your user to the admin group, perhaps this is the problematic area.
– Marged
Jul 2 '15 at 14:10
1
The authentication working correctly, but any user with any role have access to "/api/groups"
– silverhawk
Jul 2 '15 at 14:13
1
Where are you setting the ROLE 'ADMIN', can you show me that??
– We are Borg
Jul 2 '15 at 14:16
Despite the fact that role is defined correctly:
org.springframework.security.authentication.UsernamePasswordAuthenticationToken: Principal: SecurityUser; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ADMIN
– silverhawk
Jul 2 '15 at 14:17
1
here you see that authority was actually
ADMIN
and notROLE_ADMIN
. Because RoleVoter checks authorities with starting withROLE_
it can't find your authority (which isADMIN
) and thus abstains– pls
Jul 2 '18 at 11:53