I am using Spring Security 3.0.6. for modularity reasons, I would like to use properties in the security:http context.
<security:http>
...
<security:intercept-url pattern="/path/to/my/url/*" access="${token}" />
...
</security:http>
Is that possible ?
If not, if there any workaround that could be used to obtain the same behavior ?
You can use the standard PropertyPlaceholderConfigurer.
Related
I'm developing application using Spring MVC 4.X, using spring security 4.X for authentication/authorization and Thymeleaf 2.1.2 for view layer. I'm controlling access to controllers using #Secured annotion. Problem is, that Thymeleaf ignores these annotations when resolving sec:authorize-url attributes. Does anyone has working setup for this?
My security config looks like this:
<http use-expressions="true" entry-point-ref="authEntryPoint" security-context-repository-ref="sessionRepository">
<intercept-url pattern="/login/**" access="isAnonymous()"/>
<intercept-url pattern="/**" access="hasRole('USER')" />
<custom-filter position="FORM_LOGIN_FILTER" ref="usernamePasswordDomainAuthenticationFilter"/>
<logout logout-url="/logout"/>
</http>
and in servlet config, there is
<security:global-method-security secured-annotations="enabled" />
Controllers look like this:
#Secured("ROLE_EXAMPLE")
#Controller
#RequestMapping("/example")
public class ExampleController {
}
We use this Setup so security protects all controllers globally plus every controller (or controller's method if needed) can restrict access more if needed.
Everything works fine, secured controllers are not accessible for user without speciified role, thymeleaf-extras-springsecurity4 is obviously configured correctly, because sec-authorize="hasRole('EXAMPLE')" works as expected (and it takes #Secured into account).
But I feel it is prone to error to declare role both in controller and in the template, so I'd much rather use sec:authorize-url. By debugging, I found out, that it checks
if user hasRole('USER'), as declared in Security's xml config file, but it completely ignores #Secured annotations when using sec:authorize-url. In worst case, I could declare all the access in security's config file, but I like #Secured annotation much more.
Is it possible to make this setup work?
I have a Java JSF 2, Spring 3, Hibernate 4 Java EE Application which uses a third party library to authenticate the users. I imported the required CA certs into my JVM, added the third library to the project and configured in web.xml. The library reads the users details from smart card. This whole setup is working and users are taken to the home page by the third party library.
Here are my requirements to secure the application.
Check one more time if the user exist in the application specific database
Get the roles of that user from the application database
Protect my JSF pages
Protect my application services
I looked at this link and it seems "AuthenticationProcessingFilter" is deprecated and not applicable for Spring 3!
http://codersatwork.wordpress.com/2010/02/13/use-spring-security-for-authorization-only-not-for-authentication/
I also looked this one but I did not understand what other steps/configuration is needed.
spring-security: authorization without authentication
I would really appreciate if someone can outline what are all the items I need to implement Spring Security with Authorization only. This is what I came up with.
1) Update pom with spring 3 security, add a filter (which filter I should pick)
2) Custom User Detail
3) Custom DaoAuthenticationProvider
4) register this custom authentication provider in application-context.xml
5) register access decision managers for authorization
The base Spring Security classes suited for this use-case are org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter and org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider.
In case your current authentication library results in the user being authenticated in the standard Java EE way (i.e. calls to getUserPrincipal() on HttpServletRequest instance return the authenticated user's Principal) the things you need to do should be similar to:
Implement interface org.springframework.security.core.userdetails.UserDetailsService which checks that the user exists in your application database and throws UsernameNotFoundException if it doesn't
Add the following settings for the Spring Security:
<!-- Declare the user details for database check -->
<bean id="userDetails" class="com.yourpackage.DatabaseUserDetails"/>
<!-- Default empty auth manager -->
<security:authentication-manager alias="authenticationManager"/>
<!-- Use default settings from the jee namespace -->
<security:http>
<security:jee mappable-roles="IS_AUTHENTICATED_FULLY" user-service-ref="userDetails"/>
</security:http>
Configure your Spring Security to perform authorization based on your requirements
The security:jee initializes both a filter and authentication provider and plugs your user-service to the provider.
In case your current authentication library doesn't use Java EE mechanisms, you will need to implement your own subclass of the AbstractPreAuthenticatedProcessingFilter which knows how to recognize that the user has authenticated.
You would then replace the default pre-auth filter with your own, so the configuration would look like:
<!-- Declare the user details for database check -->
<bean id="userDetails" class="com.yourpackage.DatabaseUserDetails"/>
<!-- Define provider -->
<bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
<bean id="userDetailsServiceWrapper"
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<property name="userDetailsService" ref="userDetails"/>
</bean>
</property>
</bean>
<!-- Define alias for the authentication manager -->
<authentication-manager alias="authenticationManager">
<security:authentication-provider ref="preauthAuthProvider" />
</authentication-manager>
<!-- Declare the custom filter -->
<bean id="authenticationFilter" class="com.yourpackage.AuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<security:http>
<security:custom-filter ref="authenticationFilter" position="PRE_AUTH_FILTER"/>
</security:http>
You can find some more details in Spring Security documentation.
I've updated my spring security to 3.2 to be able to use Java based annotations to configure the project, without need to have an XML.
I almost configure all things, but there is 2 issues I didn't (and don't know how) to configure.
How can I configure the Http403ForbiddenEntryPoint?
How can I configure my custom AuthenticationManager?
<security:http entry-point-ref="entryPoint" >
...
</security:http>
<bean id="entryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<security:authentication-manager alias="myAuthenticationManagerImpl" />
Here is my custom authentication class:
#Service ("authenticationManager")
public class AuthenticationManagerImpl implements AuthenticationManager {
...
}
Apparently there is something in the works to address this but as it currently stands there is no way of doing this through annotations. This question seems to seeking the same answer. The standalone project in the works is here and apparently they are merging it into spring security 3.2.X sometime in the near future.
My controller:
#RequestMapping("/createchar")
#PreAuthorize("hasRole('ROLE_USER')")
public String createCharacter(Map<String, Object> map, Principal principal) {
spring-security.xml
<global-method-security pre-post-annotations="enabled"
proxy-target-class="true" />
...
<intercept-url pattern="/game*" access="ROLE_USER" />
<form-login login-page="/account/login" ...
Page is always loaded, even after redeploying the application. I haven't even logged in. Why it doesn't redirect it to login page?
If you need any more info, feel free to ask.
The controller beans typically reside inside the servlet context, so they are not affected neither by the AOP declarations nor by the bean post processors in the root application context.
Difference between applicationContext.xml and spring-servlet.xml in Spring Framework
I believe that proxying the controller classes is not a good idea, see Spring-MVC Problem using #Controller on controller implementing an interface - so I prefer to avoid using AOP on controller classes to avoid surprises - and use it only on service/DAO beans i.e. the beans in the root application context.
In this case you should use intercept-url approach for the web pages.
Being on the internship I faced the same problem. It took me and my teammates 2 days of cranching Spring Security source codes. However, today we were told that the reason of not even seeing any exceptions are "OP mechanisms", which was mentioned earlier.
The reason is the proxy class must be created.
Spring Proxy Mechanisms
So all we needed to do in our particular situation is to add
<aop:config proxy-target-class="true" />
to the app-servlet.xml
If you try to debug your code and look for methods that are invoked by Spring you may solve even similar problems (as the real cause may be different) but it is a great challenge for your patience.
Hope this will help you and others.
I was facing the same issue. My problem solved when i moved the below element from applicationContext.xml to *-servlet.xml (my dispatcher's configuration xml).
<security:global-method-security secured-annotations="enabled"/>
You have to include this element on your dispatcher's xml NOT on your application's xml.
Spring FAQ
Is there a way to force my Java EE application to use j_security_check for authentication, but not authorization? I want to do authentication through a Standalone LDAP Repository, but I want to do programmatic authorization in my application.
Specifically, I do not want to do any configuration around Authorization (user role mapping to groups) within the Websphere Application Server admin console.
For example:
User logs in with 'user1' and password 'password1' which are correct
Websphere finds this person in LDAP, knows they are who they say they are (Authentication)
I check from a file on the file system if this user is authorized or not (Authorization)
I suggest using Spring Security for this. We have implemented this exact pattern in WebSphere. The trick is to use the pre-authentication mechanism that Spring Security provides and then define only the authorization rules in the configuration.
<http>
<session-management session-fixation-protection="none"/>
<custom-filter position="PRE_AUTH_FILTER" ref="preAuthenticationFilter"/>
<intercept-url pattern="/j_security_check" filters="none"/>
<intercept-url pattern="/ibm_security_logout" filters="none"/>
<!-- put authorization intercept-url elements here... -->
</http>
You have to define some other beans as well, such as the pre-authenticated filter and a custom entry point, but that's documented here: http://static.springsource.org/spring-security/site/docs/3.0.x/reference/preauth.html
Have a look at Spring Security. The concepts of authentication and authorisation are split.
Authentication is handled by an AuthenticationProvider (an LdapAuthenticationProvider implementation is part of spring). The authentication provider delegates to fetch details of the user, which includes a list of GrantedAuthority objects which can represent a user's permissions.
LdapAuthenticationProvider by default attempts to get granted authorities from the directory, so you will need to provider your own LdapAuthoritiesPopulator implementation which loads from the file system.
Java EE Security can be split as well. It depends on your container's implementation however.
Since you mention websphere this document might be of interest.