Difference between WebExpressionVoter and AuthenticatedVoter in spring security - spring-security

What is the difference between WebExpressionVoter and AuthenticatedVoter in spring security? What I know is AuthenticatedVoter will search for strings IS_AUTHENTICATED_FULLY, IS_AUTHENTICATED_ANONYMOUSLY, IS_AUTHENTICATED_REMEMBERED (cookie) and vote for yes in corresponding cases. But I am not sure of WebExpressionVoter even afetr reading available spring docs. Please any one explain me about WebExpressionVoter. Thanks in advance.

Take a look at Web Security Expressions.
The WebExpressionsVoter is enabled by the use-expressions="true" setting on http element config. For example:
<http use-expressions="true">
<intercept-url pattern="/admin*" access="hasRole('admin')"/>
...
</http>
The above example allows you to use SpEL expressions in the intercept-url element attribute access. The expression hasRole('admin') expression is evaluated against an expression root object, for example, a base class of SecurityExpressionRoot -> WebSecurityExpressionRoot

Related

Spring Security Expression Baed Access Control with JwtAuthenticationToken

I'm working on an RESTful sevice that uses spring-boot-starter-oauth2-resource-server for security. It has some complex endpoint authorization requirements that involve decisions based not just on roles but on other claims in the JWT like location. So the HttpSecurity config's hasRole is not enough.
Is there a way to use values from the JwtAuthenticationToken with Sprng Security's expression baed access control and the HttpSecurity's access(String attribute) method? Or is there some other way to integrate different claims into endpoint authorization?
Any advice wuld be much appreciated
You have access to the Authentication object using SPEL,
so expressions like:
authentication.token.claims['preferred_username'] == ......
I have used it in methods:
e.g.
PreAuthorize("#createSupportQueryRequest.username == authentication.token.claims['preferred_username']")
public void createNewQuery(#RequestBody CreateSupportQueryRequest createSupportQueryRequest) {
But it should also work in .access method.
For more complicated stuff you can reference a bean class thats in your context in the expressions using the #.
e.g.
.access("#isPortfolioOwnerOrAdmin.check()")
This will call the check method on the IsPortfolioOwnerOrAdmin class.
Your bean class has access to the token via the SecurityConect and you can perform your complex verification logic there and return either true or false.

#Post Filter is not filtering the method returned collection using acl and oauth spring security

I m trying to integrate both Oauth security and acl spring security.
Instead of below oauth expression handler
<sec:global-method-security pre-post-annotations="enabled" proxy-target- class="true">
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
I used the acl expression handler following configuration
as explained in http://krams915.blogspot.in/2011/01/spring-security-3-full-acl-tutorial_30.html.
I am able to make acl entries in table.But while using the #PostFilter the objects returned by the method are not getting filtered using acl permission.
Can some one please help
In my configuration I made two mistakes which made #PostFilter inactive.
As told by Denim in the above comments I loaded component scan twice once by dispatcher servlet and again i loaded dispatcher servlet xml using context loader listener.With this change i was able to detect the annotation in the package where i declared the context i,e webapplication module.but in my service module the annotation was not being detected.
2 the issue in my service layer is
I had my service class as below and applied annotation as below
#Service("a")
#Transactional
Class A{
public List<Users> getUsers() {
getNames();
}
#PostFilter("hasPermission(filterObject,'edit')")
public List<Users> getNames() {
}
The annotation will not be considered as both the methods will be in the same proxy can refer
the following url
Spring AOP not working for method call inside another method

Spring Security 3 + Random Salt

So I understand that you can check a password in Spring Security with salt based on a userDetail property and then hash it to compare to a hash in the database, however what if the salt used when creating each user is random (and is stored in the DB), would I need to create my own userDetails class that contains a salt property and then set that as the field spring security uses to salt with in the securityApplicationContext?
If so how would I go about writing my own userDetails class to accomplish that? Sorry still pretty new to Spring/Java.
Ok but then how do I tell the securityApplicationContext to use myCustomUserDetails class to store the user instead of the default userDetails class?
Like this:
<b:bean id="customUserDetailsService" class="com.your.company.security.MyUserDetailsService"/>
<s:authentication-provider user-service-ref="customUserDetailsService" />
This goes in your security context.
Also this might help.
Writing a custom UserDetailsService.

what's the best way to check user's current authority in spring3 controller methods?

User's authority is frequently changed in my web service.
In this case, how do I check user's authority effectively?
I wrote code that check user's authority in every controller temporarily.
But I think this way would not good for maintenance.
How do I check user's authority without writing checking method in every controller?
Not sure what you are doing - Spring Security automatically keeps track of authorities in the User's security context. If you need to programmatically check for some other reason, then implement the HandlerInterceptor interface, and in the preHandle method, call SecurityContextHolder.getContext().getAuthentication() to get the current user. You can then check the User's authorities.
The interceptor would be configured as follows:
<mvc:interceptors>
<bean class="com.my.package.MyInterceptor" />
</mvc:interceptors>
Add an intercept-url element to your config with the role that is required, eg.
<http auto-config='true'>
<intercept-url pattern="/**" access="ROLE_FOO" />
</http>
Use HandlerMethodArgumentResolver to let Spring inject GrantedAuthority in the controller method. If a user can have more than one authority then you will need to create a class to hold user's authorities (can be named as GrantedAuthorities). After you are done, your controller method will look something like this:
#RequestMapping({"/xyz"})
public String handleXYZRequest(GrantedAuthorities authorities) {
/* use authorities if not null */
...
}
In resolver, you will use the same code that your are currently using to get authorities and it will return either null or GrantedAuthorities object. If you are using older version of Spring then use WebArgumentResolver and register it with AnnotationMethodHandlerAdapter.
Above approach avoids duplication of code and it can be used to inject anything you need from SecurityContextHolder in controller methods.
Edit
This is similar to the approach used by greenhouse. Please see WebConfig, where principal (which is Account object) is injected in controller through argument resolver.

Spring LDAP exception - No UserDetailsService registered

I am trying to use Spring Security 3.0.2 LDAP authentication for a JSF website. When I use the below configuration in applicationContext-security.xml I get this exception - org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices#0': Initialization of bean failed; nested exception is org.springframework.context.ApplicationContextException: No UserDetailsService registered.
<authentication-manager>
<ldap-authentication-provider
user-search-filter="(uid={0})" user-search-base="ou=users,ou=system"
group-search-base="ou=groups,ou=system">
</ldap-authentication-provider>
</authentication-manager>
<ldap-server id="ldapServer" url="ldap://localhost:10389"
root="" />
I just experimented and found that adding the below makes things work.
<ldap-user-service server-ref="ldapServer" user-search-filter="(uid={0})" />
But I could not find references to this in the Spring LDAP documentation. Why do I get the above exception if I do not add this? I am not happy with this workaround as I need to write user-search-filter attribute at two places.
PS: I have checked Spring Security LDAP - No UserDetailsService registered. There the exception is different and I guess the Spring Security version is different as well.
I suspect you have <remember-me/> set later in the security context. As per documentation:
http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#remember-me
If you are using an authentication provider which doesn't use a
UserDetailsService (for example, the LDAP provider) then it won't work
unless you also have a UserDetailsService bean in your application
context.

Resources