I want to put security for all the URL's except the login screen URL in spring security,
but I don't want to use session management.
Please help me out in this issue.
my security context file is below
<security:http pattern="/" security="none" />
<security:http auto-config="false" use-expressions="true" create-session="stateless" access-denied-page="/" entry-point-ref="authenticationEntryPoint" >
<security:intercept-url pattern="/**" access="isAuthenticated()" />
<security:intercept-url pattern="/logout" access="permitAll" />
<security:intercept-url pattern="/logout.jsp" access="permitAll" />
<security:logout logout-url="/j_spring_security_logout" />
<security:custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER"/>
</security:http>
The ordering of your intercept-url tags is wrong. Quote from the reference docs:
You can use multiple elements to define different access requirements for different sets of URLs, but they will be evaluated in the order listed and the first match will be used. So you must put the most specific matches at the top.
Move the intercept-url with the universal match pattern to the bottom of the list.
Related
I have an application using Spring security to control the access to its endpoints.
There are two endpoints /aaa and /bbb secured as:
<security:http pattern="/aaa/**">
<security:anonymous enabled="false" />
<security:intercept-url pattern="/aaa/**" access="isAuthenticated()" />
<security:intercept-url pattern="/aaa/**" access="#oauth2.hasScope('aaa_scope')" />
</security:http>
<security:http pattern="/bbb/**">
<security:anonymous enabled="false" />
<security:intercept-url pattern="/bbb/**" access="isAuthenticated()" />
<security:intercept-url pattern="/bbb/**" access="#oauth2.hasScope('bbb_scope')" />
</security:http>
I need to move /bbb under /aaa, i.e. to make it into /aaa/bbb while maintaining the original security checks
for the "bbb" part (now relocated)
and for the "aaa" part except for the "bbb" part parked under it.
How do I express this in Spring security XML?
What would a descriptor incantation look like?
====================
I tried the following naive combination
<security:http pattern="/aaa/bbb/**">
<security:anonymous enabled="false" />
<security:intercept-url pattern="/aaa/bbb/**" access="isAuthenticated()" />
<security:intercept-url pattern="/aaa/bbb/**" access="#oauth2.hasScope('bbb_scope')" />
</security:http>
<security:http pattern="/aaa/**">
<security:anonymous enabled="false" />
<security:intercept-url pattern="/aaa/**" access="isAuthenticated()" />
<security:intercept-url pattern="/aaa/**" access="#oauth2.hasScope('aaa_scope')" />
</security:http>
but empirically observed that it allows the holder of aaa_scope (not having bbb_scope) to access /aaa/bbb.
Apparently failing an access via first descriptor causes the request not to be aborted right there, but going on try the remaining descriptors.
Thanks for advice.
The title of the question speaks for itself.
I want both to secure home.xhtml and the clean URL /Home.
In spring security config, do i need to do what follows or is there another way of doing it ?
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/home.xhtml" access="isAuthenticated()" />
<security:intercept-url pattern="/Home" access="isAuthenticated()" />
</security:http>
Thanks
UPDATE :
Actually my solution is to be careful with files and url names.I do this in spring security file to be more coherent:
<security:intercept-url pattern="/Home*" access="isAuthenticated()" />
That secures the two URL...all url in fact beginning by Home (not case sensitive)
strange one,
I am using spring security with siteminder and it works fine. However I want to have one url which isn't protected - our loadBalancer needs a "healthCheck" url within the app itself. This url isn't intercepted by siteminder, but spring security seems to apply the preauth to it anyhow..
if I run it locally using a simple forms-based security config the following works (excluding the filters):
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/html/healthCheck.html" filters="none" />
<intercept-url pattern="/css/**" filters="none" />
<intercept-url pattern="/images/**" filters="none" />
<intercept-url pattern="/js/**" filters="none" />
<intercept-url pattern="/login" filters="none" />
<intercept-url pattern="/favicon.ico" filters="none" />
<intercept-url pattern="/*" access="hasAnyRole('ROLE_USER')" />
<form-login login-page="/login" default-target-url="/" authentication-failure-url="/loginfailed" />
<logout logout-success-url="/logout" />
</http>
In this case, I can browse to localhost/myApp/resources/html/healthCheck.html without hitting an authorization issue, but any other url will display the login form. All looking good so far!
However when I deploy to the server I am using the following config:
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/html/healthCheck.html" filters="none" />
<intercept-url pattern="/css/**" filters="none" />
<intercept-url pattern="/images/**" filters="none" />
<intercept-url pattern="/js/**" filters="none" />
<intercept-url pattern="/login" filters="none" />
<intercept-url pattern="/favicon.ico" filters="none" />
<intercept-url pattern="/*" access="hasAnyRole('ROLE_USER')" />
<custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
</http>
When I browse to: server/myapp/resources/html/healthCheck.html I get the following error:
java.lang.IllegalArgumentException: Cannot pass null or empty values to constructor
org.springframework.security.core.userdetails.User.<init>(User.java:94)
com.myApp.security.SecuritySBSUserDetailsService.loadUserByUsername(SecuritySBSUserDetailsService.java:119)
org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper.loadUserDetails(UserDetailsByNameServiceWrapper.java:53)
I think this is caused by the UserDetailsService getting instantiated without any SM_USER. Yet the filters=none is in place.. and works when using forms authentication..Any idea what might be causing this, or better - of a workaround?
By the way, my userdetails service is configured as follows:
<beans:bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<beans:property name="principalRequestHeader" value="SM_USER" />
<beans:property name="exceptionIfHeaderMissing" value="false" />
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
i.e. I've set exceptionIfHeaderMissing to false, if that helps..
The most obvious thing I can see is that /resources/html/healthCheck.html won't be matched by /html/healthCheck.html. If you are rewriting the URLs somewhere you should probably explain that.
If you enable debug logging, it should explain in detail what is matched against what.
I'd also leave out the auto-config. It causes more confusion than it is worth. And you should use /** rather than /* for a universal ant pattern match.
It's probably also worth mentioning here that Spring Security 3.1 has a better approach for defining empty filter chains, and also allows you to define more than one filter chain using the <http> syntax.
Okay, it seems to be a bug in spring security as far as I can see. I got around it by adding a dummy return to the start of the loadUserByName method in the UserDetailsService..
#Override
public UserDetails loadUserByUsername(String userName)
throws UsernameNotFoundException, DataAccessException {
logger.trace(">> loadUserByUsername()");
logger.info("-- loadUserByUsername(): username : {}", userName);
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
if(userName==null || userName.trim().equals("")) {
return(new User("ANONYMOUS", "", true, true, true, true, authorities));
}
// rest of auth checks
It would seem like with the config I have, the UserDetails check shouldn't be getting triggered at all (as it is with the forms..). If anyone has a configuration based workaround I'll give you a plus :-)
I already have form login and Basic auth working side by side with the help of a DelegatingAuthenticationEntryPoint.
What I'm trying to do is have users coming thru the login form to be authenticated against criteria "A", and have users coming thru the Basic auth requests to be authenticated against criteria "B".
Some of the application's resources are exposed thru a RESTful service (accessible via Basic auth). Instead of having users enter their own credentials to make a REST service call, they can enter generated key/value pairs for use exclusively with the REST service that can later be revoked by the user or by the app administrator.
I would prefer to share as much of my security-specific beans as possible between the two methods of authentication. I know I will need separate UserDetailsServices as the form login queries my users table, and Basic auth will query my service_credentials table.
What is the correct way to achieve this kind of configuration in Spring Security?
Depending on your app and whether you're using Spring Security 3.1, you might be best to split the configuration into multiple filter chains, each with a separate authentication manager defined:
<http pattern="/rest_api/**" create-session="stateless"
authentication-manager-ref="serviceCredsAuthMgr">
<http-basic />
</http>
<http authentication-manager-ref="mainAuthMgr">
<form-login />
</http>
<authentication-manager id="serviceCredsAuthMgr">
<authentication-provider user-service-ref="serviceCredsUserDetailsSvc" />
</authentication-manager>
<authentication-manager id="mainAuthMgr">
<!-- whatever -->
</authentication-manager>
Instead of the pattern attribute you can also use the request-matcher-ref attribute to specify a RequestMatcher instance which will be used to map incoming requests to a particular filter chain. This has a very simple interface, but can allow you to match based on something other than the URL path, such as the Accept header.
With SpringSecurity (3.2.3.RELEASE) work fine form as well as basic auth:
<http pattern="/resources/**" security="none"/>
<http pattern="/webjars/**" security="none"/>
<http pattern="/rest/**" create-session="stateless" use-expressions="true">
<intercept-url pattern="/**" access="isFullyAuthenticated()"/>
<http-basic />
</http>
<http auto-config="true" use-expressions="true">
<http-basic/>
<intercept-url pattern="/login" access="permitAll"/>
<intercept-url pattern="/loginfailed" access="permitAll"/>
<intercept-url pattern="/logout" access="permitAll"/>
<intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/**" access="isAuthenticated()"/>
<form-login login-page="/login" default-target-url="/" authentication-failure-url="/loginfailed"/>
<logout logout-success-url="/logout"/>
<remember-me user-service-ref="userService"/>
</http>
<authentication-manager>
<authentication-provider user-service-ref="userService">
<!--
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT email, password, enabled FROM users WHERE email = ?"
authorities-by-username-query="
SELECT u.email, r.name FROM users u, roles r WHERE u.id = r.user_id and u.email = ?"/>
-->
<!--
<user-service>
<user name="mail#yandex.ru" password="password" authorities="ROLE_USER"/>
<user name="admin#gmail.com" password="admin" authorities="ROLE_ADMIN"/>
</user-service>
-->
</authentication-provider>
</authentication-manager>
The default URL for my web app is http://localhost:8080/Icd/
I want to display my custom login page which is /index.jsp.
However , when I configure the spring security to do so , I am getting too many redirects problem . Below the code present in the security.xml file .
Let me know if I am missing something .
<security:http auto-config="true" >
<security:intercept-url pattern="/" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/*" access="ROLE_USER" />
<security:form-login login-page="/index.jsp" />
</security:http>
<security:authentication-provider>
<security:user-service>
<security:user name="david" password="david" authorities="ROLE_USER,ROLE_ADMIN" />
<security:user name="alex" password="alex" authorities="ROLE_USER" />
</security:user-service>
</security:authentication-provider>
When you put
<security:intercept-url pattern="/*" access="ROLE_USER" />
you're saying that every page requires ROLE_USER to be accessed (which includes the login page itself)
This (untested) may do the trick:
<security:intercept-url pattern="/index.jsp" access="permitAll"/>
<security:intercept-url pattern="/*" access="ROLE_USER" />
Try specifying your configuration like the following:
<security:http auto-config="true" use-expressions="true" access-denied-page="/krams/auth/denied" >
<security:intercept-url pattern="/krams/auth/login" access="permitAll"/>
<security:intercept-url pattern="/krams/main/admin" access="hasRole('ROLE_ADMIN')"/>
<security:intercept-url pattern="/krams/main/common" access="hasRole('ROLE_USER')"/>
<security:form-login
login-page="/krams/auth/login"
authentication-failure-url="/krams/auth/login?error=true"
default-target-url="/krams/main/common"/>
<security:logout
invalidate-session="true"
logout-success-url="/krams/auth/login"
logout-url="/krams/auth/logout"/>
</security:http>
This one uses a custom login page. For more info, you can check the full application at http://krams915.blogspot.com/2010/12/spring-security-3-mvc-using-simple-user.html