I wonder how/where can I manage Authentication at SecurityContext in pre-authentation Scenario.
I am using spring security 2.x to implement pre-authentation Scenario in my project. now, it patially work.
After user login by pre-authentation process, they can be authrozied with relevant roles, and are able to acecess resources which defined in security:filter.
e.g.
<security:filter-invocation-definition-source lowercase-comparisons="true" path-type="ant">
<security:intercept-url pattern="/resource/**" access="ROLE_ADMIN" />
In a some controller, I want to check principal in security content.
public abstract class AbstractUserAuthenticationController extends AbstractController
{
protected boolean isAuthenticated(String userName)
{
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); // where issue come up
But SecurityContextHolder.getContext().getAuthentication() always return null.
In addition, I also can not use secuiry tag in jsp to check if user has relative roles
<security:authorize ifNotGranted="ROLE_ADMIN">
no role found
</security:authorize>
Below shows the "filterChainProxy" I am using.
<bean id="filterChainProxy" class="org.springframework.security.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/*subscri*=httpSessionContextIntegrationFilter,logoutFilter,j2eePreAuthenticatedProcessingFilter,securityContextHolderAwareRequestFilter,subscribeExceptionTranslationFilter,filterInvocationInterceptor
/**=httpSessionContextIntegrationFilter,logoutFilter,j2eePreAuthenticatedProcessingFilter,logoutFilter,rememberMeProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor
</value>
</property>
</bean>
<bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService" />
</bean>
<bean id="preAuthenticatedUserDetailsService" class="demo.project.security.auth.RsaAuthenticationUserDetailsService" >
<property name="userService" ref="userService" />
</bean>
<bean id="j2eePreAuthFilter" class="demo.project.security.filter.AutoLoginFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="userService" ref="userService" />
</bean>
I think I need to set Authentication to SecurityContext in somewhere, But I do not know where/where.
What I am missing? Can anyone provide me some clues?
Thanks!
Ian
You should use SecurityContextHolder.setContext method to store your SecurityContext prior to getting it back.
The simplest way for doing this is just SecurityContextHolder.setContext(new SecurityContextImpl()).
Related
To secure my REST API's I am using #Secured({"ROLE_ADMIN", "ROLE_SUPERADMIN", ...some more} etc.
But I have to repeat this on every API manually. I found https://burtbeckwith.com/blog/?p=1398 for Groovy but couldn't find about how to do it in JAVA.
From my understanding I feel that I have to write a custom annotation (e.g. #MySecured("OnlyAdmins") ) which will work as a sort of Pre-Processor and will get replaced with the above #Secured annotation.
However I wanted to know if there is any better way to achieve the same? Also it would be really helpful if somebody could point me to some ready made custom annotation source code for achieving this.
Thanks in advance
To avoid this, create a parent role ALL_ADMINS, and setup spring security hierarchical roles, see the documentation for further details.
creating a role voter with the configured role hierarchy:
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
<constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<property name="hierarchy">
<value>
ROLE_ALL_ADMINS > ROLE_ADMIN
ROLE_ALL_ADMINS > ROLE_SUPERADMIN
...
</value>
</property>
</bean>
Then applying it to a custom access decision manager:
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<beans:property name="decisionVoters">
<beans:list>
<beans:bean ref="roleVoter" />
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</beans:list>
</beans:property>
</beans:bean>
and last configuring the custom access decision manager to be used by #Secured:
<global-method-security access-decision-manager-ref="accessDecisionManager">
...
</global-method-security>
I'm using spring authentication against ldap. If the provided user id and password exists in ldap, then I was able to get the user login. I would like to restrict this based on the user's memberOf attribute in the LDAP. If the user has memberOf attribute with a specific CN value (CN=adminaccess or CN=superadminaccess), then authentication/authorization should pass.Else authentication/authorization should fail.
<security:http auto-config="true" use-expressions="true" access-denied-page="/admin/auth/denied">
<security:intercept-url pattern="/admin/auth/login" access="permitAll" />
<security:intercept-url pattern="/admin/dashboard/*" access="hasAnyRole('ROLE_ADMINACCESS','ROLE_SUPERADMINACCESS')"/>
</security:http>
<security:authentication-manager>
<security:ldap-authentication-provider user-dn-pattern="CN={0},CN=Users" group-search-base="CN=adminaccess,CN=Users" />
</security:authentication-manager>
<bean id="ldapContext"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://xxx.ds.yyy.com:389/DC=xxx,DC=ds,DC=yyy,DC=com"/>
<property name="userDn" value="CN=aaa,CN=Users,DC=xxx,DC=ds,DC=yyy,DC=com"/>
<property name="password" value="thepassword"/>
</bean>
I always go to the Access Denied page with my above configuration. If I remove the access="hasAnyRole('ROLE_ADMINACCESS','ROLE_SUPERADMINACCESS')" from the security:intercept-url, I'm able to always access with valid user/password, even if the user is not part of adminaccess (which I was hoping would be restricted because my group -search-base had specified CN=adminaccess).
Wondering what the configuration should be:
To restrict access to just users who are memberOf CN=adminaccess and/or CN=superadminaccess
Specify correct group-search-base. If I specify only CN=Users, I'm getting a timeout as this is going against our corporate ldap. When I looked up users on LDAP browser, I couldnt find a "ou" that couldhelp. With my above configuration group-search-base="CN=adminaccess,CN=Users", I dont get a timeout, but I dont think it is correct either
Not sure if there is a better way, but I was able to successfully get this working using DefaultLdapAuthoritiesPopulator and updating to the below configuration:
<security:http auto-config="true" use-expressions="true" access-denied-page="/admin/auth/denied">
<security:intercept-url pattern="/admin/auth/login" access="permitAll" />
<security:intercept-url pattern="/admin/dashboard/*" access="hasAnyRole('ROLE_ADMINACCESS','ROLE_SUPERADMINACCESS')"/>
</security:http>
<security:authentication-manager>
<security:authentication-provider
ref="ldapAuthProvider"></security:authentication-provider>
</security:authentication-manager>
<bean id="ldapContext"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://xxx.ds.yyy.com:389/DC=xxx,DC=ds,DC=yyy,DC=com"/>
<property name="userDn" value="CN=aaa,CN=Users,DC=xxx,DC=ds,DC=yyy,DC=com"/>
<property name="password" value="thepassword"/>
</bean>
<bean id="ldapAuthProvider"
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg>
<bean
class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="ldapContext" />
<property name="userDnPatterns">
<list>
<value>CN={0},CN=Users</value>
</list>
</property>
</bean>
</constructor-arg>
<constructor-arg>
<bean
class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="ldapContext" />
<constructor-arg value="CN=Users" />
<property name="groupRoleAttribute" value="CN" />
</bean>
</constructor-arg>
</bean>
With this configuration, if the login username/password provided is correct, all the groups that the user is "memberOf" (pattern CN=Users,DC=xxx,DC=ds,DC=yyy,DC=com), get loaded as his "roles" (prefixed with ROLE_) and I'm able to manage access to these roles using security:intercept-url
I am currently trying to implement remember me functionality in my website. Following is part of my configuration
<security:remember-me services-ref="rememberMeServices" />
<bean id="rememberMeServices" class="com.entertainment.ecom.web.auth.EcomRemembe rMeServices">
<property name="userDetailsService" ref="ecomUserDetailsService"/>
<property name="key" value="a23eef6dfd1514cb885f47070380ff18"/>
<property name="cookieName" value="ENTC"/>
<property name="tokenValiditySeconds" value="80000"/>
</bean>
My EcomRememberMeServices extends AbstractRememberMeServices & I have overridden onLoginFail & onLoginSuccess methods. My question is, from where my onLoginSuccess() method will be called?
I have tried to run above configuration & it was seen that onLoginFail gets called through RememberMeAuthenticationFilter(rememberMeServices.loginFail(request, response)) but when I checked source code for this filter, I could not find any call for onLoginSuccess() or loginSuccess() method. So do I need to call this explicitly?
In BasicAuthenticationFilter, there is a call for this method. So I tried to use it but still i does not work.(<http-basic/>). So can anyone please help me in this?
There is one more method logout(), which is called by logout filter. I guess you have to inject rememberMeServices into Login and Logout Filter as well (I am not sure if it can be done within http element in xml):
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg index="0" type="org.springframework.security.web.authentication.logout.LogoutSuccessHandler" ref="logoutSuccessHandler" />
<constructor-arg index="1">
<list value-type="org.springframework.security.web.authentication.logout.LogoutHandler">
<ref local="rememberMeServices"/>
</list>
</constructor-arg>
</bean>
and
<bean id="formLoginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
...
<property name="rememberMeServices">
<ref local="rememberMeServices" />
</property>
</bean>
In our app spring security uses ldap as a provider.
i am working on a change that will let you flip a flag in dev that will allow you to log in if your user/pass matches a value from database. the ldap server might be down and you can still log in.
What ive realized though is that some urls are secured with
#Secured( {"ROLE_USER","ROLE_MERCHANT"})
so i need to still have some dealings with spring security in order for my logins to work. How do i go about doing this?
You can configure 2 providers: one LDAP provider and another DAO provider.
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="yourLdapAuthenticationProvider" />
<sec:authentication-provider ref="yourDaoAuthenticationProvider" />
</sec:authentication-manager>
If the LDAP fails, it will fall back to DAO authentication provider.
You will need to configure your own authentication filter to inject that flag into yourDaoAuthenticationProvider so that when the authentication falls back to yourDaoAuthenticationProvider, it can check whether to proceed with further authentication (say, in development) or ignore it (say, in production). So, in your authenticationFilter, override setDetails() to store the flag:-
myAuthenticationFilter bean
#Override
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
YourObject yourObject = new YourObject(request.getParameter("devAuthAgainstDAO"));
authRequest.setDetails(yourObject);
}
With this, have your yourDaoAuthenticationProvider to check against this flag before proceeding with further authentication.
In the end, your configuration will look something like this:-
<sec:http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint">
<sec:logout logout-success-url="/login.jsp"/>
<sec:intercept-url ... />
<sec:custom-filter position="FORM_LOGIN_FILTER" ref="myAuthenticationFilter"/>
</sec:http>
<bean id="myAuthenticationFilter" class="[YOUR_CUSTOM_AUTHENTICATION_FILTER]">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationFailureHandler" ref="failureHandler"/>
<property name="authenticationSuccessHandler" ref="successHandler"/>
</bean>
<bean id="loginUrlAuthenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
</bean>
<bean id="successHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/welcome.jsp"/>
<property name="alwaysUseDefaultTargetUrl" value="true"/>
</bean>
<bean id="failureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login.jsp?login_error=1"/>
</bean>
<bean id="yourLdapAuthenticationProvider" ... />
<bean id="yourDaoAuthenticationProvider" ... />
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="yourLdapAuthenticationProvider"/>
<sec:authentication-provider ref="yourDaoAuthenticationProvider"/>
</sec:authentication-manager>
I'm having trouble discovering exactly what I need to implement in order to use a custom authentication method with my web application using Spring Security. I have a Grails application with the Spring Security plugin that currently uses the standard user/password authentication with a browser form. This is working correctly.
I need to implement a mechanism alongside of this that implements a type of MAC authentication. If the HTTP request contains several parameters (e.g. a user identifier, timestamp, signature, etc.) I need to take those parameters, perform some hashing and signature/timestamp comparisons, and then authenticate the user.
I'm not 100% sure where to start with this. What Spring Security classes do I need to extend/implement? I have read the Reference Documentation and have an okay understanding of the concepts, but am not really sure if I need a Filter or Provider or Manager, or where/how exactly to create Authentication objects. I've messed around trying to extend AbstractProcessingFilter and/or implement AuthenticationProvider, but I just get caught up understanding how I make them all play nicely.
Implement a custom AuthenticationProvider which gets all your authentication information from the Authentication: getCredentials(), getDetails(), and getPrincipal().
Tie it into your Spring Security authentication mechanism using the following configuration snippet:
<bean id="myAuthenticationProvider" class="com.example.MyAuthenticationProvider">
<security:custom-authentication-provider />
</bean>
This step is optional, if you can find a suitable one from standard implementations. If not, implement a class extending the Authentication interface on which you can put your authentication parameters:
(e.g. a user identifier, timestamp, signature, etc.)
Extend a custom SpringSecurityFilter which ties the above two classes together. For example, the Filter might get the AuthenticationManager and call authenticate() using your implementation of Authentication as input.
You can extend AbstractAuthenticationProcessingFilter as a start.
You can reference UsernamePasswordAuthenticationFilter which extends AbstractAuthenticationProcessingFilter. UsernamePasswordAuthenticationFilter implements the standard Username/Password Authentication.
Configure your Spring Security to add or replace the standard AUTHENTICATION_PROCESSING_FILTER. For Spring Security Filter orders, see http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html#filter-stack
Here is a configuration snippet for how to replace it with your implementation:
<beans:bean id="myFilter" class="com.example.MyAuthenticationFilter">
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/>
</beans:bean>
I have recently put up a sample application that does custom authentication with Spring Security 3.
The source code is here.
More details are in this blog post.
Here is an example of securityContext.xml configuration file using custom autenticationFilter (extending AUTHENTICATION_PROCESSING_FILTER) and authenticationProvider. The user authentication data is provided by jdbc connection. Configuration is for Spring Security 2.0.x
<?xml version="1.0" encoding="UTF-8"?>
<sec:global-method-security />
<sec:http auto-config="false" realm="CUSTOM" create-session="always" servlet-api-provision="true"
entry-point-ref="authenticationProcessingFilterEntryPoint" access-denied-page="/notauthorized.xhtml"
session-fixation-protection="migrateSession">
<sec:port-mappings>
<sec:port-mapping http="80" https="443" />
</sec:port-mappings>
<sec:anonymous granted-authority="ROLE_ANONYMOUS" username="Anonymous" />
<sec:intercept-url pattern="/**" access="ROLE_ANONYMOUS, ROLE_USER" />
<sec:logout logout-url="/logoff" logout-success-url="/home.xhtml" invalidate-session="false" />
</sec:http>
<bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.xhtml" />
<property name="forceHttps" value="false" />
</bean>
<bean id="authenticationProcessingFilter" class="mypackage.CustomAuthenticationProcessingFilter">
<sec:custom-filter position="AUTHENTICATION_PROCESSING_FILTER" />
<property name="defaultTargetUrl" value="/" />
<property name="filterProcessesUrl" value="/logon" />
<property name="authenticationFailureUrl" value="/loginError.xhtml" />
<property name="alwaysUseDefaultTargetUrl" value="false" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<jee:jndi-lookup id="securityDataSource" jndi-name="jdbc/DB_DS" />
<bean id="myUserDetailsService" class="mypackage.CustomJdbcDaoImpl">
<property name="dataSource" ref="securityDataSource" />
<property name="rolePrefix" value="ROLE_" />
</bean>
<bean id="apcAuthenticationProvider" class="mypackage.CustomDaoAuthenticationProvider">
<property name="userDetailsService" ref="myUserDetailsService" />
<sec:custom-authentication-provider />
</bean>
<bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<list>
<ref local="apcAuthenticationProvider" />
</list>
</property>
</bean>
</beans>