how to change default-target-url depending on user role - spring-security

I use spring security for user authentication. In security.xml I have
<form-login login-page="/login"
default-target-url="/dashboard"
always-use-default-target="false"
authentication-failure-url="/login/error"
login-processing-url="/j_security_check"/>
I want to be able to configure different target urls for different user roles. How do i do this?
Thanks!

If you're using Spring-Security 3.0 or higher implementing your own AuthenticationSuccessHandler is the way to go:
<sec:form-login ... authentication-success-handler-ref="successHandler"/>
...
<bean id="successHandler" class="de.....MySpecialAuthenticationSuccessHandler">
Then MySpecialAuthenticationSuccessHandler can extend one of the default handlers like SavedRequestAwareAuthenticationSuccessHandler though they are not really inheritance-friendly.

see -
http://forum.springsource.org/showthread.php?t=93541

I don't think you can configure this, but your default-target-url dashboard can contain logic to redirect to appropriate page based on the role.

Related

SPEL expressions not evaluated dynamically

I am trying to filter URLs using spring security. Following is a definition for filtering:
<intercept-url pattern="/page" access="#{new java.io.File('file_path').exists()}"/>
The URL is restricted based on existence of a file called file_path.
If the file_path exists at the time the spring configuration file is loaded, the access is provided. If the file_path is created after load, access is not provided. I would like the expression to be evaluated every time the request to /page is made & not just during compilation of the expression.
Tried to set the system property -Dspring.expression.compiler.mode=MIXED but there is no effect.
Can anybody please help me in this?
That's correct because you use the configuration time expression (#{...}). To achieve the requirements you should use something like this:
<http use-expressions="true">
<intercept-url pattern="/admin*"
access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/>
</http>
See Expression-Based Access Control. So, in your case it can be like this:
<http use-expressions="true">
<intercept-url pattern="/page" access="new java.io.File('file_path').exists()"/>
</http>

Spring security: share intercept-url between configuration

I have two different configuration of spring security, one for local development and the other per test and production server. They are quite different but need to share the "intercept-url" part.
Consither this:
<security:http ... >
<security:http-basic />
<security:anonymous />
<security:intercept-url ... />
<security:intercept-url ... />
...
</security:http>
I need to share the list of the intercept-url tags between two different http tags.
Is there a way to do this?
That's not something you can easily do with the namespace.
If you are just defining access constraints, one possibility might be to define an external filter-security-metadata-source and write a BeanPostProcessor to inject it into the FilterSecurityInterceptor.
However, it's probably not worth the trouble for something like this.
Another option would be to externalize the authentication filters you want to use as beans (use the custom-filter element to add them to the <http> configuration) and configure them separately depending on your environment. It would be easier to suggest how feasible that is if you could post both configurations explicitly to see how much overlap there is.

How to list *all* users and *all* authorities in a Spring Security application

Q1) Is there a way (ie a class method) in Spring Security that allows you to list all the users and roles that is in the Sprint Security user & roles tables? (I'm not looking for only logged in users; and I'm not looking for only the authorities for a given user. I'm looking for all users and all authorities.)
Q1b) If there is a way, does the user running this query need special permissions?
(I can hack this by writing my own SQL statement that queries the users and authorities table, but that seems like unecessary work, prone to mistakes, and breaks the Spring Security API.)
In case it helps, my application context setup is fairly standard:
<authentication-manager alias="myAuthenticationManager">
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select username, password, enabled from users where users.username=?"
authorities-by-username-query="select users.username,authority from users,authorities where users.username=authorities.username and users.username=?" />
</authentication-provider>
</authentication-manager>
and
<beans:bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<beans:property name="driverClassName">
<beans:value>com.mysql.jdbc.Driver</beans:value>
</beans:property>
<beans:property name="url">
<beans:value>jdbc:mysql://XXXXX:XXXX/XXXXX</beans:value>
</beans:property>
<beans:property name="username">
<beans:value>XXXXX</beans:value>
</beans:property>
<beans:property name="password">
<beans:value>XXXXXX</beans:value>
</beans:property>
</beans:bean>
Spring Security implementation solve very specific task and in most cases this task needs only one user. So many of Spring Security queries contain user filter "where username = ?". You could easily check all available queries by downloading sources and searching for string ["select ].
So, you should write your own queries (JDBC or Hibernate) in your DAO-layer for your tasks.
No - looking at the API for JdbcUserDetailsManager which you are using there are no methods to list all users or list all authorities. You'll need to write custom code to do it.

where to put filter like logic in JSF2

I am currently banging my head where to put a common logic for some authorization stuff in my Java EE 6/JSF 2 webapp:
I have the requirement, that all requests that come with a specific cookie should be redirected to another page.
I considered 3 solutions:
1) use a servlet 3.0 filter (#WebFilter)
this worked, i also could inject my managed beans there, but the managed beans require access to the faces externalContext, which at filter invocation time has not yet been set up, so i got NPE's calling the managed beans
2) use a phase listener
this feels awkward, because a phase listener cannot be a CDI component and so cannot inject other components (except via el-evaluation); a phaseListener for me feels to technical to put navigation logic into it.
3) in Seam 2.0 i could used "page actions" for things like this, but it seems that this concept didn't make it into JSF 2.0
in seam this looked like:
<page view-id="/admin/*.jsf">
<action execute="#{authenticator.checkAccess()}" />
</page>
Is it really, that JSF 2.0 does not have a concept to execute "controller logic" before rendering a page?
In JSF 2.x you can listen to page events like that:
<f:metadata>
<f:event type="javax.faces.event.PreRenderViewEvent" listener="#authenticator.checkAccess()}" />
</f:metadata>
That is more or less equivalent to Seam 2 page action (you will have to filter out postbacks though). You can further enhance the default behavior with CDI-extensions like Seam Faces. Probably it's a good idea if you have a look at the documentation and see what fits your needs...

Spring security - how to mention both form based and basic authentication

Is it possible to mention both form-based and basic authentication in Spring security using namespace configuration without overriding other ? So that the appliciation could serve both browser based request and remoting client.
The response by #grimesjm is right. However, if you are using Spring 3.x you have to adapt the class names to:
<bean id="basicProcessingFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<property name="authenticationManager">
<ref bean="authenticationManager" />
</property>
<property name="authenticationEntryPoint">
<ref bean="authenticationEntryPoint" />
</property>
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
<property name="realmName" value="Your realm here" />
</bean>
And
<sec:http auto-config="true">
... your intercept-url here
<sec:custom-filter before="SECURITY_CONTEXT_FILTER" ref="basicProcessingFilter" />
<sec:form-login ... />
....
</sec:http>
I do not know whether placing the filter before SECURITY_CONTEXT_FILTER is the best option or not.
The end result you want is possible, I have ran into that exact same problem and here is my solution.
Anytime when defining form-login in the namespace it will override automatically any other authentication filters you apply via namespace. This is done through the ordering of the filter chain look at FilterChainOrder.java in the spring security to see how the order is actually applied to each filter.
To get around this remove the http-basic tag from the namespace then manually define the bean to handle basic authentication and place its order before the AuthenticationProcessingFilter because this is the spring security filter that will handle the form-login.
The BasicProcessingFilter spring provides to handle Basic authentication is a passive filter, meaning that if the credentials are missing it will continue down the filter chain until it finds the appropriate filter to handle the request.
Now by manually defining the BasicProcessingFilter bean we can set the order that it will appear in the filter chain.
Below is an example of the additional xml declarations you will need to supply in the security xml (Spring Security < 3.x)
<bean id="basicProcessingFilter" class="org.springframework.security.ui.basicauth.BasicProcessingFilter">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<security:custom-filter before="AUTHENTICATION_PROCESSING_FILTER"/>
<property name="authenticationEntryPoint"><ref bean="authenticationEntryPoint"/></property>
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.ui.basicauth.BasicProcessingFilterEntryPoint">
<property name="realmName" value="My Realm Here"/>
</bean>
Also note if your authenticationManager reference isn't found you can add an alias to your namespace like the one below.
<security:authentication-manager alias="authenticationManager"/>
The end result is the basic filter will be applied as a passive filter and if its required credentials are missing it will continue down the filter chain and the form-login filter will then handle it.
The problem with this approach is that if credentials are correctly entered, the response back is the login page from the form-login filter.
However, It appears that this problem will be fixed by spring in version 3.1 of spring security and this work around will no longer be needed.
It is now possible with Spring Security 3.1.0
It seems that it is not possible to declare both form and basic authentication using namespace configuration.
A reference link to spring community :
http://forum.springsource.org/showthread.php?t=72724&highlight=form+basic+authentication

Resources