How do I enable logging for Spring Security? - debugging

I am setting up Spring Security to handle logging users in. I have logged in as a user, and am taken to an Access Denied error page upon successful login. I don't know what roles my user has actually been assigned, or the rule that causes access to be denied, because I can't figure out how to enable debugging for the Spring Security library.
My security xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans ... >
<!-- security -->
<security:debug/><!-- doesn't seem to be working -->
<security:http auto-config="true">
<security:intercept-url pattern="/Admin**" access="hasRole('PROGRAMMER') or hasRole('ADMIN')"/>
<security:form-login login-page="/Load.do"
default-target-url="/Admin.do?m=loadAdminMain"
authentication-failure-url="/Load.do?error=true"
username-parameter="j_username"
password-parameter="j_password"
login-processing-url="/j_spring_security_check"/>
<security:csrf/><!-- enable Cross Site Request Forgery protection -->
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:jdbc-user-service data-source-ref="loginDataSource"
users-by-username-query="SELECT username, password, active FROM userinformation WHERE username = ?"
authorities-by-username-query="
SELECT ui.username, r.rolename
FROM role r, userrole ur, userinformation ui
WHERE ui.username=?
AND ui.userinformationid = ur.userinformationid
AND ur.roleid = r.roleid "
/>
<security:password-encoder hash="md5"/>
</security:authentication-provider>
</security:authentication-manager>
</beans>
I've also tried adding log4j.logger.org.springframework.security=DEBUG to my log4j.properties
How can I get debug output for Spring Security?

Assuming you're using Spring Boot, another option is to put the following in your application.properties:
logging.level.org.springframework.security=DEBUG
This is the same for most other Spring modules as well.
If you're not using Spring Boot, try setting the property in your logging configuration, e.g. logback.
Here is the application.yml version as well:
logging:
level:
org:
springframework:
security: DEBUG

You can easily enable debugging support using an option for the #EnableWebSecurity annotation:
#EnableWebSecurity(debug = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
…
}

Basic debugging using Spring's DebugFilter can be configured like this:
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.debug(true);
}
}

You can easily enable debugging support using an option for the #EnableWebSecurity annotation:
#EnableWebSecurity(debug = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
…
}
If you need profile-specific control the in your application-{profile}.properties file
org.springframework.security.config.annotation.web.builders.WebSecurity.debugEnabled=false
Get Detailed Post: http://www.bytefold.com/enable-disable-profile-specific-spring-security-debug-flag/

We can always check the registered filters inside Spring Security with the below configuration
#EnableWebSecurity(debug=true) - We need to enable the debugging of the security details
Enable logging of the details by adding the below property in the application.properties logging.level.org.springframework.security.web.FilterChainProxy=DEBUG
Below mentioning some of the internal filters of Spring Security that gets executed in the authentication flow:
Security filter chain: [
CharacterEncodingFilter
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
X509AuthenticationFilter
UsernamePasswordAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
RememberMeAuthenticationFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]

Using Spring Boot with default spring security filters (without customizing anything, and without even setting debug in the EnableWebSecurity annotation), setting TRACE as the following application.properties shows:
logging.level.org.springframework.security=TRACE
Is enough for it to show in detail what filters are being called and what they are doing.
TRACE w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
TRACE w.c.HttpSessionSecurityContextRepository : Created SecurityContextImpl [Null authentication]
DEBUG w.c.HttpSessionSecurityContextRepository : Created HttpSession as SecurityContext is non-default
...
DEBUG o.s.security.web.FilterChainProxy : Securing POST /api/product/productname01
TRACE o.s.security.web.FilterChainProxy : Invoking WebAsyncManagerIntegrationFilter (1/16)
...
TRACE o.s.security.web.FilterChainProxy : Invoking CsrfFilter (5/16)
DEBUG o.s.security.web.csrf.CsrfFilter : Invalid CSRF token found for http://localhost/api/product/productname01
DEBUG o.s.s.w.access.AccessDeniedHandlerImpl : Responding with 403 status code
Versions:
Spring Framework Bom version 5.3.16
Spring Boot 2.6.4
Spring 5.3.16
Spring Security 5.6.2

Spring security logging for webflux reactive apps is now available starting with version 5.4.0-M2 (as mentionned by #bzhu in comment How do I enable logging for Spring Security?)
Until this gets into a GA release, here is how to get this milestone release in gradle
repositories {
mavenCentral()
if (!version.endsWith('RELEASE')) {
maven { url "https://repo.spring.io/milestone" }
}
}
// Force earlier milestone release to get securing logging preview
// https://docs.spring.io/spring-security/site/docs/current/reference/html5/#getting-gradle-boot
// https://github.com/spring-projects/spring-security/pull/8504
// https://github.com/spring-projects/spring-security/releases/tag/5.4.0-M2
ext['spring-security.version']='5.4.0-M2'
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}

You have two options:
1. Set the logging level of Spring Security to debug or trace:
application.yml:
logging:
level:
org:
springframework:
security: debug # or trace
application.properties:
logging.level.org.springframework.security=debug
2. Enable the Spring Security debug mode
#Configuration
#EnableWebSecurity
public class SecurityConfig {
#Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return web -> web.debug(true);
}
}
or like this:
#Configuration
#EnableWebSecurity(debug = true)
public class SecurityConfig {
}

Related

Resource server with Spring Security 5 issue with SecurityContextPersistenceFilter in SpringSecurityChain

I faced a problem with Resource Server in Spring Security 5. I'm using spring security 5.3.7 and spring boot in version 2.7.4 with dependecy:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
My problem is with getting 401 Unauthorized response when I using Postman to get to secured resource. I set up my configuration server according to Spring docs https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html#oauth2resourceserver-jwt-minimaldependencies.
Below it's my configuration:
Controller class:
#PreAuthorize("hasAuthority('EXAMPLE')")
#RestController
public class MyController {
#GetMapping("/example")
public List<Something> myMethod(Principal auth) {
return ...
}
Configuration of my resource server with JWT + Key usecase:
#Configuration
#EnableWebSecurity(debug = true)
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityResourceServerConfig {
#Value("${spring.security.oauth2.resourceserver.jwt.key-value}")
private String signingKey;
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated())
.oauth2ResourceServer((oauth2) -> oauth2.jwt((jwt) -> jwt.decoder(jwtDecoder())))
.cors();
return http.build();
}
#Bean
public JwtDecoder jwtDecoder() {
byte[] secretByte = signingKey.getBytes();
SecretKey secretKey = new SecretKeySpec(secretByte, 0, secretByte.length, "RSA");
return NimbusJwtDecoder.withSecretKey(secretKey).build();
}
#Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
grantedAuthoritiesConverter.setAuthorityPrefix("");
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
return jwtAuthenticationConverter;
}
For logging my SecurityFilterChain i added #EnableWebSecurity(debug = true) and to application.yml
logging:
level:
org:
springframework:
security: DEBUG
When I make request to endpoint #GetMapping("/example"). I get 401 Unauthorized code. When I check logs of my service I see:
Security filter chain: [
DisableEncodeUrlFilter
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CorsFilter
CsrfFilter
LogoutFilter
BearerTokenAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
AuthorizationFilter
]
************************************************************
2022-10-01 16:16:54.912 DEBUG 1 --- , [http-nio-8080-exec-8] o.s.security.web.FilterChainProxy.doFilterInternal - Securing GET /roles
2022-10-01 16:16:54.913 DEBUG 1 --- , [http-nio-8080-exec-8] o.s.s.w.c.SecurityContextPersistenceFilter.doFilter - Set SecurityContextHolder to empty SecurityContext
2022-10-01 16:16:54.922 DEBUG 1 --- , [http-nio-8080-exec-8] o.s.s.w.c.HttpSessionSecurityContextRepository.saveContext - Did not store empty SecurityContext
2022-10-01 16:16:54.922 DEBUG 1 --- , [http-nio-8080-exec-8] o.s.s.w.c.SecurityContextPersistenceFilter.doFilter - Cleared SecurityContextHolder to complete request
So, my question is why am I getting 401 Unathorized code without configure any SecurityContextPersistenceFilter and any persisten configuration explicitly and BearerTokenAuthenticationFilter is not executed to Authenticate mu request?

Spring Security with Spring Boot

I am trying to create a Spring Boot REST application. When I deploy my application, it authentication is required and it is asking me for user name and password. How can I bypass this or how can I add a user name and password for authentication?
Do I need to remove security entry in pom?
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
If you don't want to use authentication at all, you should remove the dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
See Spring Boot Reference Guide:
If Spring Security is on the classpath then web applications will be secure by default with ‘basic’ authentication on all HTTP endpoints.
No need of removing security from pom.xml. In your project, you can try something like below. Try to create SecurityConfig which will extend WebSecurityConfigurerAdapter and provide some user name and password and later you can customize it.
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("user")
.roles("USER")
.and()
.withUser("user2")
.password("secret2")
.roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().fullyAuthenticated();
http
.httpBasic();
http
.csrf().disable();
}
}
public #interface EnableWebMvcSecurity {
}
Apart from other two answers - default username is 'user' and password will be printed in the console each time you start your server like below -
2019-08-31 23:58:16.417 INFO 12528 --- [ restartedMain] .s.s.UserDetailsServiceAutoConfiguration :
Using generated security password: 1ab46edf-332a-42de-ae11-70dc138c65db
Simply use these credentials to login.
Note - If you fine-tune your logging configuration, ensure that the org.springframework.boot.autoconfigure.security category is set to log INFO-level messages. Otherwise, the default password is not printed.
if you wish to configure a username/password of your choice then you can do so in application.properties file.
spring.security.user.name=username
spring.security.user.password=password
Now spring security will not generate a new password each time you boot the application.
Note: When using postman to send requests, go to authorization> select "basic auth"> Enter the username and password so authentication details can be sent along with each request. If using browser, there should be a login page.

spring security custom-filter with java configuration

How can I replace default filter with custom filter in java configuration? In XML it would be, for example:
<bean id="myFilter" class="lalalal.MyFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<security:http auto-config="true">
<security:custom-filter ref="myFilter" position="FORM_LOGIN_FILTER"/>
</security:http>
About filterBefore, filterAfter and default filter inhereting I know.
Assuming you have an understanding in general of Java configuration for Spring-security, adding filters is relatively simple (general details of updating spring-security config to java here):
So in your WebSecurityConfigurerAdapter implementation, do something like this:
#Configuration
#EnableWebSecurity
class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override protected void configure(HttpSecurity http) throws Exception {
//Custom security filters
http.addFilterBefore( myFilter(), BasicAuthenticationFilter.class );
//Rest of the security configuration goes here
...
}
That is a very cut down example - but hopefully helps enough - you would put additional security configuration here (e.g. role based restrictions, csrf, session config etc) and myFilter() is another method defining the bean you mention in the question that sets up your Filter. There is also an addFilterAfter() method and you can choose where to place your filter in the chain.
Here is an example for API security that shows some custom filters being used.

make every request https in spring security 3.2

I am using spring security 3.2 using the namespace configuration, and I want to make all the calls to be https. I know it would decrease the performance by about 1/10, but I still want to implement it. I know you/might achieve this from tomcat itself, but i want to configure it in security.xml
You can configure that https is required by adding requires-channel attribute on each intercept-url. For example:
<http>
<intercept-url pattern="/secure/**" access="ROLE_ADMIN" requires-channel="https"/>
<intercept-url pattern="/**" access="ROLE_USER" requires-channel="https"/>
</http>
You can configure this more concisely using Spring Security Java Configuration. Notice that we can separate the channel configuration from the role mappings. For example:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/secure/**").hasRole("ADMIN")
.anyRequest.hasRole("USER")
.and()
.requiresChannel()
.anyRequest().requiresSecure();
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
As of Spring Security 3.2 you also might want to ensure you use Spring Security's headers support. This is enabled by default in Spring Security Java Configuration. In this specific case, the element can add a header called Strict-Transport-Security to the response that ensures that browsers do not even make HTTP requests in the future. For example:
<headers>
<hsts/>
</headers>
You will want to read more about this in the Headers section of the reference.

PreAuthorize doesn't work

I'm writing a socket server (no web-application !) application and want to use method-based security to handle my ACL needs. i followed a small tutorial i found spring security by example
so far i configured:
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler" />
</security:global-method-security>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator">
<bean id="permissionEvaluator" class="myPermissionEvaluator" />
</property>
</bean>
<security:authentication-manager id="authenticationmanager">
<security:authentication-provider ref="authenticationprovider" />
</security:authentication-manager>
<bean id="authenticationprovider" class="myAuthenticationProvider" />
With a service bean:
#Named
public class ChannelService {
#PreAuthorize("isAuthenticated() and hasPermission(#channel, 'CHANNEL_WRITE')")
public void writeMessage(Channel channel, String message) { ... }
}
Everything compiles and the application starts and works fine, but without access control. My debug log shows that my Evaluator is never called.
When i tried something similar with a #Secured annotation the annotation was evaluated and access was denied. but simple role based security isn't enough for my requirements.
EDIT
did some more tests: when i configure only secured-annotations="enabled" the role based security works. when configure pre-post-annotations="enabled" in ADDITION neither secured nor preauthorize works. when i configure only pre-post-annotations it still doesn't work.
EDIT2
some more tests:
with only secured_annotations="enabled" the call to my channelservice goes through the Cglib2AopProxy
as soon as i activate pre-post-annotations the call lands directly in the channelservice. no interceptor, no proxy, nothing.
I'm getting kind of desperate...
EDIT3
I debug-logged my testruns here is the part for spring-security
with only secured-annotations="enabled"
2012-04-12 13:36:46,171 INFO [main] o.s.s.c.SpringSecurityCoreVersion - You are running with Spring Security Core 3.1.0.RELEASE
2012-04-12 13:36:46,174 INFO [main] o.s.s.c.SecurityNamespaceHandler - Spring Security 'config' module version is 3.1.0.RELEASE
2012-04-12 13:36:49,042 DEBUG [main] o.s.s.a.m.DelegatingMethodSecurityMetadataSource - Caching method [CacheKey[mystuff.UserService; public void mystuff.UserService.serverBan(java.lang.String,mystuff.models.User,org.joda.time.DateTime)]] with attributes [user]
2012-04-12 13:36:49,138 DEBUG [main] o.s.s.a.i.a.MethodSecurityInterceptor - Validated configuration attributes
2012-04-12 13:36:49,221 DEBUG [main] o.s.s.a.m.DelegatingMethodSecurityMetadataSource - Caching method [CacheKey[mystuff.ChannelService; public void mystuff.ChannelService.writeMessage(mystuff.models.Channel,java.lang.String)]] with attributes [blubb]
2012-04-12 13:36:51,159 DEBUG [main] o.s.s.a.ProviderManager - Authentication attempt using mystuff.GlobalchatAuthenticationProvider
2012-04-12 13:36:56,166 DEBUG [Timer-1] o.s.s.a.ProviderManager - Authentication attempt using mystuff.GlobalchatAuthenticationProvider
2012-04-12 13:36:56,183 DEBUG [Timer-1] o.s.s.a.i.a.MethodSecurityInterceptor - Secure object: ReflectiveMethodInvocation: public void mystuff.ChannelService.writeMessage(mystuff.models.Channel,java.lang.String); target is of class [mystuff.ChannelService]; Attributes: [blubb]
2012-04-12 13:36:56,184 DEBUG [Timer-1] o.s.s.a.i.a.MethodSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#312e8aef: Principal: mystuff.UserId#ced1752b; Credentials: [PROTECTED]; Authenticated: true; Details: null; Not granted any authorities
Exception in thread "Timer-1" org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AbstractAccessDecisionManager.checkAllowIfAllAbstainDecisions(AbstractAccessDecisionManager.java:70)
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:88)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:205)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at mystuff.ChannelService$$EnhancerByCGLIB$$3ad5e57f.writeMessage(<generated>)
at mystuff.run(DataGenerator.java:109)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
2012-04-12 13:36:56,185 DEBUG [Timer-1] o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.RoleVoter#1cfe174, returned: 0
2012-04-12 13:36:56,185 DEBUG [Timer-1] o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter#da89a7, returned: 0
with pre-post-annotations="enabled"
2012-04-12 13:39:54,926 INFO [main] o.s.s.c.SpringSecurityCoreVersion - You are running with Spring Security Core 3.1.0.RELEASE
2012-04-12 13:39:54,929 INFO [main] o.s.s.c.SecurityNamespaceHandler - Spring Security 'config' module version is 3.1.0.RELEASE
2012-04-12 13:39:54,989 INFO [main] o.s.s.c.m.GlobalMethodSecurityBeanDefinitionParser - Using bean 'expressionHandler' as method ExpressionHandler implementation
2012-04-12 13:39:59,812 DEBUG [main] o.s.s.a.ProviderManager - Authentication attempt mystuff.GlobalchatAuthenticationProvider
2012-04-12 13:39:59,850 DEBUG [main] o.s.s.a.i.a.MethodSecurityInterceptor - Validated configuration attributes
As far as i understand this log output spring doesn't realize my beans need to be proxied, so they aren't and so i don't get security.
EDIT4
I debug-logged the complete sprint startup... (thats one big log) and there i find:
2012-04-12 14:40:41,385 INFO [main] o.s.c.s.ClassPathXmlApplicationContext - Bean 'channelService' of type [class mystuff.ChannelService] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
is there a way to figure out why? because as far as i understand it. because of #preauthorize the bean should be eligible. with only secured-annotations="enabled" i get a post processing log.
This configuration worked just as expected for me:
<bean id="securityExpressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" />
<bean id="preInvocationAdvice"
class="org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice"
p:expressionHandler-ref="securityExpressionHandler" />
<util:list id="decisionVoters">
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter"
c:pre-ref="preInvocationAdvice" />
</util:list>
<bean id="accessDecisionManager"
class="org.springframework.security.access.vote.UnanimousBased"
c:decisionVoters-ref="decisionVoters" />
<sec:global-method-security
authentication-manager-ref="authenticationManager"
access-decision-manager-ref="accessDecisionManager"
pre-post-annotations="enabled" />
I got the log message:
WARN org.springframework.security.access.expression.DenyAllPermissionEvaluator -
Denying user jack permission 'CHANNEL_WRITE' on object Channel[ name=null ]
And an exception:
org.springframework.security.access.AccessDeniedException: Access is denied
From a simple test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:META-INF/spring/application-context.xml")
public class SpringSecurityPrePostTest {
#Autowired
ChannelService channelService;
#Test
public void shouldSecureService() throws Exception {
Authentication authentication = new UsernamePasswordAuthenticationToken("jack", "sparrow");
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(authentication);
channelService.writeMessage(new Channel(), "test");
}
}
One thing I did diffrent was to use interface on a service and JDK proxies instead of cglib:
public interface ChannelService {
void writeMessage(Channel channel, String message);
}
and:
#Component
public class ChannelServiceImpl implements ChannelService {
private static final Logger LOG = LoggerFactory.getLogger(ChannelServiceImpl.class);
#Override
#PreAuthorize("isAuthenticated() and hasPermission(#channel, 'CHANNEL_WRITE')")
public void writeMessage(Channel channel, String message) {
LOG.info("Writing message {} to: {}" , message, channel);
}
}
UPDATE1:
With this simplified config I get the same result:
<bean id="securityExpressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" />
<sec:global-method-security
authentication-manager-ref="authenticationManager"
pre-post-annotations="enabled">
<sec:expression-handler ref="securityExpressionHandler" />
</sec:global-method-security>
UPDATE2:
The debug message from Edit4 indicates that channelService may not have bean proxied at all as it got classified as not eligible for auto-proxying. This qiestion answers similar problem - try not to use #Autowired or any other mechanism based on BeanPostProcessors to set up the beans involved in security checks (i.e. myPermissionEvaluator).
UPDATE3:
You cannot use secured resources (i.e. services) within beans responsible for security checks! This creates a dependency loop and is a error in Your configuration. You must use lover level access (i.e. DAO) to check permissions, anything that is not secured! Implementing security checks using secured resources is not what You want to do.
If despite using not secured resources with #Autowired things don't work as expected, try using old-school XML confiuration style for all beans involved in security checks. Also remember that <context:component-scan /> is in fact a BeanDefinitionRegistryPostProcessor and introduces the scanned beans into the BeanFactory after all the ones declared in XML are already there.
it works,
make sure that you have <sec:global-method-security pre-post-annotations="enabled"/> in your spring servlet (ie where you may have your <mvc:annotation-driven/>)
"sec" is from xmlns:sec="http://www.springframework.org/schema/security"

Resources