I'm using Spring Security 3.2.4 and trying to determine where it gets its default configuration from. For example, when using the following configuration:
<http use-expressions="true">
<intercept-url pattern="/secure/login" access="permitAll" />
<intercept-url pattern="/secure/logout" access="permitAll" />
<intercept-url pattern="/secure/denied" access="permitAll" />
<session-management session-fixation-protection="migrateSession" session-authentication-error-url="/login.jsp?authFailed=true">
<concurrency-control max-sessions="10" error-if-maximum-exceeded="true" expired-url="/login.html" session-registry-alias="sessionRegistry"/>
</session-management>
<intercept-url pattern="/**" access="isAuthenticated()" />
<form-login login-page="/secure/login" default-target-url="/" authentication-failure-url="/secure/denied" />
<logout logout-url="/secure/logout" logout-success-url="/" />
<expression-handler ref="defaultWebSecurityExpressionHandler" />
</http>
Something in a Spring configuration somewhere, is telling Spring to instantiate the LoginUrlAuthenticationEntryPoint and set the login-page to "/secure/login", etc. I realize that it is the form-login tag that is doing this magic for me, but where within Spring is the form-login tag translated to mean the LoginUrlAuthenticationEntryPoint, etc?
Similarly, by default, Spring will instantiate a filter chain of name org.springframework.security.filterChains, but can't find where that bean is defined. I presume it is in an xml configuration file within one of the Spring Security jars, but I can't find it anywhere.
Where are all these defaults configured?
Check out SecurityNamespaceHandler and work your way down from there. As you can see, it is in the spring-security-config artifact, in package org.springframework.security.config.
Related
At the moment a basic REST API has 3 URL's (not actual URL's)
http://localhost:8080/app
http://localhost:8080/app/home
http://localhost:8080/app/product
Currently all three URL's have basic authentication using Spring Security using XML.
However, I would like to remove the basic authentication for URL 1.
I have unsuccessfully tried the following the following approaches (reduced XML)
<http>
<intercept-url pattern="/app/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
<http-basic/>
</http>
vs
<http>
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
<intercept-url pattern="/app/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<http-basic/>
</http>
Is there something I'm missing in my configuration or there is another way to achieve this using Spring Security?
If you set the context path of your server to 'app' so all the paths in your application will be localhost:8080/app/**.
If you want to allow everyone to access all the paths in the application and only for authenticated users to access /home and /product you should do this:
<http>
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/home" access="IS_AUTHENTICATED_FULLY" />
<intercept-url pattern="/product" access="IS_AUTHENTICATED_FULLY" />
<http-basic/>
</http>
This way everyone will get to localhost:8080/app but only IS_AUTHENTICATED_FULLY users will access to /home & /product.
Shouldn't you be doing something like this:
<http>
<intercept-url pattern="/app/**" access="IS_AUTHENTICATED_FULLY"/>
<intercept-url pattern="/app/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<http-basic/>
</http>
I've created a webservice with spring roo and added spring security to the project. Everything works fine so far but now I want to allow to access entities information via HTTP GET requests without any authentication. The other HTTP methods like POST, PUT etc. should stay secure.
My applicationContext-security.xml looks like the following but when I do a HTTP GET on "/releaseupdates/" with a "Accept: application/json" header it always returns the login page (I think spring security redirects to the login page internally):
<http auto-config="true" use-expressions="true">
<form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t" />
<logout logout-url="/resources/j_spring_security_logout" />
<!-- Configure these elements to secure URIs in your application -->
<intercept-url pattern="/releaseupdates/**" access="permitAll" method="GET" />
<intercept-url pattern="/releaseupdates/**" access="hasRole('ROLE_ADMIN')" method="POST" />
<intercept-url pattern="/releaseupdatestatuses/**" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/choices/**" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/member/**" access="isAuthenticated()" />
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/login/**" access="permitAll" />
<intercept-url pattern="/**" access="isAuthenticated()" />
</http>
There is also an annotation #PreAuthorize which could be your friend here. The annotation could be at class or method level on your Controllers.
Here's an example:
#Controller
#RequestMapping("/releaseupdates")
public class ReleaseUpdateController {
#RequestMapping(method=RequestMethod.GET)
public String unprotectedGetRequest() {
//do something, no protection
}
#PreAuthorize("hasRole('ROLE_ADMIN')")
#RequestMapping(method=RequestMethod.POST)
public String securePostRequest() {
//do something, secured
}
}
I'm writing a RESTful web service that requires multiple authentication mechanisms (basic, x509, and anonymous). I therefore have three <http> elements in three separate spring context files.
When I start my service, I'm getting the following exception:
org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [org.springframework.security.web.SecurityFilterChain]
is defined: expected single matching bean but found 3:
org.springframework.security.web.DefaultSecurityFilterChain#0,
org.springframework.security.web.DefaultSecurityFilterChain#1,
org.springframework.security.web.DefaultSecurityFilterChain#2
I think this makes sense, right? I've defined three <http> elements, so spring is probably creating three instances of org.springframework.security.web.DefaultSecurityFilterChain. And now someone is asking for a bean of type org.springframework.security.web.SecurityFilterChain, and is finding three.
But, according to Spring Security documentation, this is supposed to be possible, so my question is: How do I get this scenario to work?
Here are my three <http> configurations:
x509Auth.xml:
<sec:http pattern="/service/x509/**" use-expressions="true">
<sec:x509 subject-principal-regex="(.*)" user-service-ref="ldapUserDetailsService" />
<sec:intercept-url pattern="/service/x509/identity/**" access="hasRole('Domain Users')" />
</sec:http>
basicAuth.xml:
<sec:http pattern="/anubis/basic/**" use-expressions="true" create-session="stateless">
<sec:intercept-url pattern="/service/basic/identity/**" access="isAuthenticated()" />
<sec:http-basic />
</sec:http>
noAuth.xml:
<sec:http pattern="/service/anonymous/**" security="none" />
Thanks to this InfoQ post, I learned that with new flexibility comes new responsibility. Since you can have multiple <http> elements now, you can also have multiple authentication managers. This requires us to tell spring which authentication manager goes with each<http> element.
Here is my now-working spring configuration:
<!-- This section configures X509 Certificate Authentication -->
<sec:http
pattern="/service/x509/**"
use-expressions="true"
authentication-manager-ref="ldapAuthenticationManager">
<sec:x509 subject-principal-regex="(.*)" user-service-ref="ldapUserDetailsService" />
<sec:intercept-url pattern="/service/x509/identity/**" access="hasRole('Domain Users')" />
</sec:http>
<sec:authentication-manager alias="ldapAuthenticationManager">
<sec:authentication-provider user-service-ref="ldapUserDetailsService" />
</sec:authentication-manager>
<!-- This section configures BASIC Authentication -->
<sec:http
pattern="/service/basic/**"
use-expressions="true"
create-session="stateless"
authentication-manager-ref="mongoAuthenticationManager">
<sec:http-basic />
<sec:intercept-url pattern="/service/basic/identity/**" access="isAuthenticated()" />
</sec:http>
<sec:authentication-manager alias="mongoAuthenticationManager">
<sec:authentication-provider user-service-ref="mongoUserDetailsService" />
</sec:authentication-manager>
<!-- This section configures NO Authentication -->
<sec:http pattern="/service/anonymous/**" security="none" />
I have a java web application running on Tomcat 7.
I am using Spring 3.2 with Spring Security 3.1 on the backend, and am exposing an API via RESTful URLs following the /api/** pattern.
The UI for the web application is built using BackboneJS. I am using Backbone models mapped directly to the RESTful URLS.
The UI is locked down using form-login authentication, so the user is always redirected to the login screen if they have are not currently authenticated.
I am now attempting to expose the same RESTful URLs to another external service using http-basic authentication. Unfortunately, when securing the same URL pattern, it seems Spring will not allow me to use more than one filter chain. Whichever is defined first in the configuration file seems to take precedence.
I would hate to have to map to separate URL patterns for the same RESTful resources, but it seems like I may not have a choice.
Here is the important sample of my (currently broken) spring security configuration:
<!-- configure basic http authentication -->
<http pattern="/api/**" create-session="stateless">
<intercept-url pattern="/**" access="ROLE_USER"/>
<http-basic/>
</http>
<!-- configure form-login authentication -->
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/ui/login" access="permitAll" />
<intercept-url pattern="/ui/logout" access="permitAll" />
<intercept-url pattern="/ui/loginfailed" access="permitAll" />
<intercept-url pattern="/**" access="ROLE_USER" />
<custom-filter ref="ajaxTimeoutRedirectFilter" after="EXCEPTION_TRANSLATION_FILTER" />
<form-login login-page="/ui/login" default-target-url="/" authentication-failure-url="/ui/loginfailed" />
<logout logout-success-url="/ui/logout" />
<session-management invalid-session-url="/ui/login"/>
</http>
My question is:
Is it possible to configure two different types of security (http-basic and form-login) for the same URL patterns using Spring Security? Is there a best practice for this type of scenario?
Thank you.
Why don't you just merge the two <http> elements like this:
<http pattern="/api/**" use-expressions="true">
<intercept-url pattern="/ui/login" access="permitAll" />
<intercept-url pattern="/ui/logout" access="permitAll" />
<intercept-url pattern="/ui/loginfailed" access="permitAll" />
<intercept-url pattern="/**" access="ROLE_USER" />
<http-basic/>
<custom-filter ref="ajaxTimeoutRedirectFilter" after="EXCEPTION_TRANSLATION_FILTER" />
<form-login login-page="/ui/login" default-target-url="/" authentication-failure-url="/ui/loginfailed" />
<logout logout-success-url="/ui/logout" />
<session-management invalid-session-url="/ui/login"/>
</http>
This would set up both a UsernamePasswordAuthenticationFilter and a BasicAuthenticationFilter in the same filter chain which could serve the ui client, and the external service as well.
Not possible out of the box to apply 2 different filter chain for a single URL pattern.
But it is a advisable to have unique URL patterns as UI and API, as you would have to apply a completely different filter chain in future.
For example the SecurityContextRepository hold the session information and is retrieved for each request. You don't want to apply the same for UI and API access through basic auth
Try to replace pattern="/" by pattern="/api/" in API config:
<http pattern="/api/**" create-session="stateless">
<intercept-url pattern="/api/**" access="ROLE_USER"/>
<http-basic/>
</http>
I have problems with double authentication. I have implemented the authentication form through pop-up window which is always on top. But I have problem probably with interceptors that cause the authentication request by Tomcat even before the start of application:
A username and password are being requested by http://127.0.0.1:8888.
The site says: "Spring Security Application"
If I disable interceptors, I see in log that SecurityContextHolder treats user as Anonymous.
So my question is:
Can I somehow disable that first Tomcat login screen?
My Spring-security configuration XML is:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customAuthenticationProvider"/>
</authentication-manager>
<beans:bean id="customAuthenticationProvider" class="com.myCompany.model.security.CustomAuthenticationProvider" >
<beans:property name="databaseId" value="${configuration.databaseId}" />
<beans:property name="applicationId" value="${configuration.applicationId}" />
</beans:bean>
<http auto-config="true" >
<intercept-url pattern="/myApp/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/MyApp.html*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/gwt/**" access="ROLE_USER"/>
<intercept-url pattern="/**/*.html" access="ROLE_USER"/>
<intercept-url pattern="/css/**" filters="none"/>
<intercept-url pattern="/**" access="ROLE_USER" />
<http-basic />
</http>
<global-method-security secured-annotations="enabled" />
</beans:beans>
In case I understand your question in a correct way you have a problem with double authentication e.g. a Tomcat authentication or an Apache Basic Auth and the Spring authentication mechanism.
While the last project I had related problems with an Apache Basic Auth and the Spring security mechanism. Before launch I had the task to "protect" the access to the site by an simple Apache Basic Auth. By enabling this in the Apache configuration Spring started to do the same: "Spring Security Application" has been shown all the time
The solution for this behaviour was to disable the auto-config:
<security:http auto-config="false" ...>
...
</security:http>
Your question is not too clear. You mention a Tomcat login screen, which I assume is the first screen of your web application, to allow a user to sign in.
If this is correct, and your login page is named, say login.html, all you have to do is configure the interceptors to allow anonymous access to this page-
<intercept-url pattern="/**/login.*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/gwt/**" access="ROLE_USER"/>
<intercept-url pattern="/**/*.html" access="ROLE_USER"/>
<intercept-url pattern="/css/**" filters="none"/>
<intercept-url pattern="/**" access="ROLE_USER" />