Spring Security configuration supporting multiple subsites based on Hippo CMS - java

I am trying to use spring security based on hippo cms plugin. I have created inside hippo 3 subsites which are having each login. How should I config the spring-security-context.xml in order to support multiple subsites? All subsites will use the same authenticationprovider. Till now I have configured one of the subsites.
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/beans/spring-lang-3.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- HTTP Security Configuration -->
<!-- HTTP Security Configuration -->
<http auto-config="true">
<intercept-url pattern="/css/**" />
<intercept-url pattern="/images/**" />
<intercept-url pattern="/binaries/**" />
<intercept-url pattern="/vop/**" access="IS_AUTHENTICATED_ANONYMOUSLY, ROLE_everybody" />
<form-login login-page="/vop"
default-target-url="/vop/vop-mysurvey-page"
always-use-default-target="true" />
<logout logout-url="/logout.jsp" logout-success-url="/vop"/>
</http>
<!--
Authentication Manager configuration with Hippo Repository based Authentication Provider configuration ('hippoAuthenticationProvider').
However, you can use any other authentication provider(s) if you don't need to authenticate users against Hippo Repository.
-->
<authentication-manager>
<authentication-provider ref="hippoAuthenticationProvider"/>
</authentication-manager>
<!--
Hippo Repository based Authentication Provider. This Authentication Provider provide authentication against Hippo Repository Security Store.
If you don't need to authenticate users against Hippo Repository, you don't have to include the following bean.
-->
<beans:bean id="hippoAuthenticationProvider"
class="org.onehippo.forge.security.support.springsecurity.authentication.HippoAuthenticationProvider">
</beans:bean>
For example I want to have also <http auto-config="true">
<intercept-url pattern="/css/**" />
<intercept-url pattern="/images/**" />
<intercept-url pattern="/binaries/**" />
<intercept-url pattern="/erop/**" access="IS_AUTHENTICATED_ANONYMOUSLY, ROLE_everybody" />
<form-login login-page="/erop"
default-target-url="/erop/mypage"
always-use-default-target="true" />
<logout logout-url="/logout.jsp" logout-success-url="/erop"/>
</http>
Any Ideas?

As far as I know, spring security framework is based on servlet filter and its configuration seems to be tied to a web application context. Because of that, I don't think you can host multiple spring security contexts in single web application context currently.

Spring security supports securing multiple subsites. The configuration depends a bit on your subsites, whether they use separate host names or not.
When your subsites run under the same host name, you can configure it like this:
<http pattern="/vop/**" ... >
...
</http>
<http pattern="/erop/**" ... >
...
</http>
However, if your subsites run on different host names, it could be that the url patterns overlap. In this case you need to filter by host name, something like:
<bean id="vopMatcher" class="org.springframework.security.web.util.ELRequestMatcher">
<constructor-arg value="hasHeader('host','vop.com')"/>
</bean>
<bean id="eropMatcher" class="org.springframework.security.web.util.ELRequestMatcher">
<constructor-arg value="hasHeader('host','erop.com')"/>
</bean>
<http request-matcher-ref ="vopMatcher" ... >
...
</http>
<http request-matcher-ref ="eropMatcher" ... >
...
</http>

Related

Could not verify the provided CSRF token because your session was not found

I've been searching about this problem but still cannot be avoid. The problem only come when I'm trying to make an ajax call. The system will return error Could not verify the provided CSRF token because your session was not found.
Based from Spring MVC and CSRF Integration, I need to included #EnableWebSecurity to resolve this if I'm using Java Config, but if using XML, need to use this :
#RestController
public class CsrfController {
#RequestMapping("/csrf")
public CsrfToken csrf(CsrfToken token) {
return token;
}
}
And I'm not sure how to use above class.
The question is how to use above class if its really a solution or are there any solution I can use?
This is my security config xml file;
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- Global Security Settings -->
<global-method-security pre-post-annotations="enabled" />
<context:component-scan base-package="com.my.web" />
<!-- Reads WEB Configuration file to resolve ${} and read #Value for Security-->
<context:property-placeholder location="classpath:cfg/web.cfg" />
<context:annotation-config />
<!-- Security Access Configuration -->
<http auto-config="false" use-expressions="true" authentication-manager-ref="CAP" disable-url-rewriting="true" entry-point-ref="IAE">
<session-management session-fixation-protection="newSession" session-authentication-error-url="/logout?timeout" >
<concurrency-control max-sessions="1" expired-url="/logout?expired" />
</session-management>
<custom-filter position="PRE_AUTH_FILTER" ref="entryFilter" />
<intercept-url pattern="/resources/**" access="permitAll()" requires-channel="https" />
<intercept-url pattern="/clearcache" access="permitAll()" requires-channel="https" />
<intercept-url pattern="/logout" access="permitAll()" requires-channel="https" />
<intercept-url pattern="/**" access="isFullyAuthenticated()" requires-channel="https" />
<port-mappings >
<port-mapping http="7001" https="7002" />
</port-mappings>
<headers>
<frame-options policy="SAMEORIGIN" />
<hsts />
<cache-control />
<xss-protection />
<content-type-options />
</headers>
</http>
<beans:bean id="entryFilter" class="com.my.web.security.HeaderFilter" >
<beans:property name="authenticationManager" ref="CAP"/>
</beans:bean>
<beans:bean id="IAE" class="com.my.web.security.CustomAuthenticationEntryPoint" />
<beans:bean id="CAP" class="com.my.web.security.CustomAuthenticationManager" />
<beans:import resource="../aop/aspect-security.xml" />
</beans:beans>
In addition, I'm a using system similar like CA Siteminder which will validated the user based on header info with no login form.
Spring requires sending the csrf token on every form submit. To accomplish this is possible for example to insert the following code into a JSP:
<form>
[...]
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
[...]
</form>
Best regards
I' new to SO and this is my first answer, so bear with me.
This is what has to be done before doing AJAX calls when using jQuery:
$(document).ready(
function() {
var token = $("meta[name='_csrf']").attr("content");
$.ajaxSetup({
headers : {
"X-CSRF-Token" : token
}
});
});
THIS IS THE ANSWER!
Ok so here the thing, from other question that literally have the same cause, mostly it will affect system that using Rest, header without form login. This mean that the webapp is in the container system. So the location of both system either container and the system in the container is completely different at client side.
Here are the example..
For container webapp:
www.myweb.com/main/
For webapp in container:
www.myweb.com/main/child
This different will denied the access and give the 403 because for sure the this we are looking in are not exist there.
Example:
www.myweb.com/main/child/playground
The /playground uri is exist there but for sure is forbidden here:
www.myweb.com/main/playground
So please check your uri and try to make sure you are using a relative path. Its much more better.
P/s:For some reason, everything that being called from server side remain intact either the container or the system in the container.This happen because the server side using relative path,not absolute path.

How can I exclude a specific resource from Spring Security management and make it accessible also to the not logged users?

I am pretty new in Spring Security and I have the following problem.
I have this controller method that handle request toward the /riepilogoCentrale resource
#RequestMapping(value = "/riepilogoCentrale", method = RequestMethod.GET)
public String riepilogoUtenteCentrale(HttpServletRequest request, Model model, Locale locale) {
System.out.println("INTO riepilogoUtenteCentrale()");
return "centrale/riepilogoCentrale";
}
My problem is that this resource (so the related rendered page) have to be accessible to everyone (also the not logged user) and as it is actually configured Spring Security if I try to access to this resource as visitor (not logged user) Spring redirects me to the log in page.
This is my Spring Security configuration file (named spring-security.xml):
<?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-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.0.xsd">
<http pattern="/resources/**" security="none"/>
<http auto-config="true" use-expressions="true" authentication-manager-ref="authenticationManager">
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/registrati" access="permitAll" />
<intercept-url pattern="/salvaRegistrazione" access="permitAll" />
<intercept-url pattern="/captcha.html" access="permitAll" />
<intercept-url pattern="/**" access="isAuthenticated()" />
<logout logout-success-url="/login" logout-url="/logout" />
<form-login login-page="/login"
authentication-failure-url="/login?error=true"
default-target-url="/"
username-parameter="nomeUtente"
password-parameter="password"
login-processing-url="/j_spring_security_check"/>
<csrf disabled="true"/>
</http>
<authentication-manager id="authenticationManager" >
<authentication-provider>
<jdbc-user-service data-source-ref="datasource"
users-by-username-query="select des_usr_par, des_psw_par,true from TID001_ANAGPARTECIPA where des_usr_par =?"
authorities-by-username-query="select des_usr_par, prg_par from TID001_ANAGPARTECIPA where des_usr_par = ? "/>
</authentication-provider>
</authentication-manager>
</beans:beans>
So, how can I exclude the /riepilogoCentrale from the Spring Security management and make it accessible also to the not logged users ?
You're already doing this for some of your resources; for example:
<intercept-url pattern="/salvaRegistrazione" access="permitAll" />
I would imagine that you'd add another intercept-url value including /riepilogoCentrale as the pattern, and implement other business logic inside of your controller based on whether or not the user is authenticated.
You are already excluding some resources.
<http pattern="/resources/**" security="none"/>
Just add the same entry with your riepilogoCentrale-resource.

Reject access to specific URLs for all the ROLEs in Spring Security

This is my spring-security.xml
<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.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/dashboard.htm" access="hasAnyRole('ROLE_USER','ROLE_ADMIN','ROLE_DEMO')"/>
<intercept-url pattern="/dash/*" access="hasAnyRole('ROLE_USER','ROLE_ADMIN','ROLE_DEMO')"/>
<form-login login-page="/index.htm"
default-target-url="/dashboard.htm"
authentication-failure-url="/loginfailed.htm" />
<logout logout-success-url="/logout.htm" invalidate-session="true" />
</http>
<beans:bean id="customUserService" class="edu.am.bigdata.web.service.impl.CustomUserServiceImpl"></beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="customUserService">
<password-encoder hash="md5"> </password-encoder>
</authentication-provider>
</authentication-manager>
</beans:beans>
how to prevent access to one particular Url???
I have some controller functions (i.e.) urls - /dash/* , /algo/*
I need to prevent this url even if user possess any ROLE and show it as access Denied only if he directly access these urls. But my web application internally uses this URL.
If I type this url manually like localhost:8080/MyApp/dash/viz.htm, this should show access denied. For any Roles these urls should not be accessed.. How can I do this ???
Use access = "denyAll". For example:
<intercept-url pattern="/admin/*" access="denyAll" />

Spring's SecurityContextHolder.getContext().getAuthentication() returns null after RedirectView is used in HTTPS/SSL

I have a typical Spring MVC running on Tomcat. After switching the system to run on HTTPS (everything is working OK under plain HTTP), the login stopped working. The reason is that Spring's SecurityContextHolder.getContext().getAuthentication() object becomes null after RedirectView is used.
I already searched for the answer, the only one I found suggested to set property redirectHttp10Compatible to false in the viewResolver bean setup. This did not help.
I also checked that throughout redirect, my session id remains the same and the connection remains secure, i.e. it is not an issue (at least as far as I could tell) of a change between http and https or vice versa.
What could be the problem?
<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.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http auto-config="true">
<intercept-url pattern="/**" requires-channel="https" />
<intercept-url pattern="/index*" access="ROLE_USER"/>
<intercept-url pattern="/dashboard*" access="ROLE_USER" requires-channel="https"/>
<intercept-url pattern="/login*" access="ROLE_GUEST, ROLE_ANONYMOUS, ROLE_USER"/>
<intercept-url pattern="/signin*" access="ROLE_GUEST, ROLE_ANONYMOUS, ROLE_USER"/>
<intercept-url pattern="/signup*" access="ROLE_GUEST, ROLE_ANONYMOUS, ROLE_USER"/>
<form-login login-page="/home"
default-target-url="/home"
authentication-failure-url="/home?authentication_error=true"
authentication-success-handler-ref="redefineTargetURL"
/>
<anonymous username="guest" granted-authority="ROLE_GUEST" key="anonymousKey"/>
<logout invalidate-session="true" logout-success-url="/logout?message=Logout Successful" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="userDetailsService" />
</authentication-manager>
<beans:bean id="redefineTargetURL" class="com.groupskeed.common.RedefineTargetURL" />
<beans:bean id="userDetailsService" class="com.groupskeed.security.UserDetailsServiceImpl" />
The SecurityContextHolder.getContext().getAuthentication() becoming null after redirect is correct since it is threadbound. But it should be repopulated from the session. Therefore try to keep track of the SPRING_SECURITY_CONTEXT Attribute in the Session. Here is some example code to get an idea:
HttpSession session = request.getSession(true);
System.out.println(session.getAttribute("SPRING_SECURITY_CONTEXT"));
In the Spring Security documentation there is a Part about how HTTPS/HTTP switching can screw up the session perhaps there is a hint to your problem somewhere in there.
http://static.springsource.org/spring-security/site/faq.html#d0e223
The above FAQ leads to an examination of how the session is handled in your application.
I probably would start looking at the AuthenticationSuccessHandler implementation. (You can post it into your question if you like.)
For more detail on how the security context is handled in web applications see the following: (section 5.4 Authentication in a Web Application): http://static.springsource.org/spring-security/site/docs/3.0.x/reference/technical-overview.html

Missing ROLE_ANONYMOUS in Spring Security

I have been using Spring Security 2.x for some time now, but recently I switched to 3.x. I always use my own implementation of UserDetails interface and authentication against DB.
Everything works fine (logging in, logging out, url filters, seeing username of authorized user, etc.).
The only thing left to do was to display "Please login" message when user is not authorized. I tried few approaches:
<sec:authorize access="not isAnonymous()">
or
<sec:authorize access="hasRole('ROLE_ANONYMOUS')">
etc.
None of them worked. Finally I added <sec:authentication property="principal.authorities" /> to my home page output to debug what roles user really has. This is what I see:
Logged user - [ROLE_USER, ROLE_ADMIN]
Unathorized user - `` <- empty String
It looks like I somehow lost the default ROLE_ANONYMOUS authority, which was always added by Spring, if I recall correctly. Was that recently dropped or something? Perhaps I have to take care of this anonymous access in some other manner?
Relevant part of security context:
<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.1.xsd">
<!-- UNPROTECTED RESOURCES -->
<http pattern="/" security="none"/>
<http pattern="/favicon.ico" security="none"/>
<http pattern="/home" security="none"/>
<http pattern="/login*" security="none"/>
<http pattern="/resources/**" security="none"/>
<!-- PROTECTED RESOURCES -->
<http auto-config='true' use-expressions="true">
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/admin/**" access="hasRole('ROLE_USER,ROLE_ADMIN')"/>
<form-login login-page="/login" default-target-url="/dashboard" authentication-failure-url="/login?login_error=true"/>
<logout logout-url="/logout"/>
</http>
<beans:bean id="userAccountsAuthenticationProvider" class="pl.xxx.utils.UserAccountsAuthenticationProvider" />
<beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
<beans:property name="userPropertyToUse" value="salt" />
</beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userAccountsAuthenticationProvider">
<password-encoder ref="standardPasswordEncoder"/>
</authentication-provider>
</authentication-manager>
</beans:beans>
Anonymous Authentication can be configured in few different ways - do you use <http auto-config="true">, <anonymous> tag or define beans by yourself as custom filter? It'll be easier if you posted your security-context.xml.
Anyway, you want to display "Please login", so I assume you really wanted
<sec:authorize access="isAnonymous()">Please login</sec:authorize>
without "not" (by the way I can't find if "not" is a valid part of expression in this context).
Another way is to use isAuthenticated() instead, negate it in EL and see if it works in your case:
<sec:authorize access="isAuthenticated()" var="isAuthenticated" />
<c:if test="${not isAuthenticated}">
<!-- do stuff -->
</c:if>
EDIT:
Change security="none" to access="IS_AUTHENTICATED_ANONYMOUSLY" and move chosen patterns to intercept-url. It should enable Spring Security's Filter Chain and apply AnonymousAuthenticationFilter on request:
<!-- UNPROTECTED RESOURCES -->
<http pattern="/favicon.ico" security="none"/>
<http pattern="/resources/**" security="none"/>
<!-- PROTECTED RESOURCES -->
<http auto-config='true' use-expressions="true">
<intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/home" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/admin/**" access="hasRole('ROLE_USER,ROLE_ADMIN')"/>
<form-login login-page="/login" default-target-url="/dashboard" authentication-failure-url="/login?login_error=true"/>
<logout logout-url="/logout"/>
</http>
assuming you want use isAnonymous() in /, /home and /login*.
My previous solution worked, because with security="none" checking for isAuthenticated() always yielded false, so negating it was like checking for not being loggged.

Categories