I am facing this problem...
I have the spring security filter
on my web.xml
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I am using spring security and I have this at my springSecurity-applicationContext.xml
<http
authentication-manager-ref="myAuthManager"
access-decision-manager-ref="accessDecisionManager"
entry-point-ref="authenticationEntryPoint"
create-session="ifRequired"
access-denied-page="/unauthorized">
<custom-filter ref="myPreAuthenticatedFilter" position="PRE_AUTH_FILTER"/>
<logout logout-success-url="/page/home"/>
<anonymous key="anonymous"/>
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/method/do" access="IS_AUTHENTICATED_ANONYMOUSLY()"/>
</http>
So, at myPreAuthenticationFilter I have a filter that extends of AbstractPreAuthenticatedProcessingFilter
I am trying to execute /method/do with a DELETE or a POST without success.
I am wondering what would be the best way to do it?
For some reason when I put a break point on myPreAuthenticationFilter at doFilter and make the request with DELETE nothing happens, only when I do the GET.
I want that endpoint to have no security.
I made this and worked
<http pattern="/method/do" security="none"/>
Not sure why this works and others dont or where I should look for.
Any idea?
The errors I get are Forbidden
If using spring-security 4 or above, csrf filter is enabled by default and it actually blocks any POST, PUT or DELETE requests which do not include de csrf token.
If you are not sending the csrf token in any of this kind of requests, you should make a test just disabling it configuring <csrf disabled="true"/> in your secured <http> section in your security xml, this way:
<http
authentication-manager-ref="myAuthManager"
access-decision-manager-ref="accessDecisionManager"
entry-point-ref="authenticationEntryPoint"
create-session="ifRequired"
access-denied-page="/unauthorized">
<custom-filter ref="myPreAuthenticatedFilter" position="PRE_AUTH_FILTER"/>
<logout logout-success-url="/page/home"/>
<anonymous key="anonymous"/>
<intercept-url pattern="/method/do" access="IS_AUTHENTICATED_ANONYMOUSLY()"/>
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<csrf disabled="true"/>
</http>
Edit
I have just realized that the order of the intercept-url should be just the opposite, starting from the most specific and ending with the most generic (I have already modified in the sample configuration I suggested)
In your case, it does not affect the behaviour given that both mappings have same access policy, but it should be this way.
I have a weird problem and not able to fix it.
The Problem :
I login to my Spring web application which has long session timeout, whenever I quit the browser and then reopen it, access my web-app and I see login page every time.
It works fine as long as browser is not closed. I thought that there is some problem with the chrome settings, but it's not. Also it happens with all the browsers.
My web.xml:
<session-config>
<session-timeout>10000</session-timeout>
<cookie-config>
<name>myapp</name>
<http-only>true</http-only>
</cookie-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
My Spring Security configuration:
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/resources/**" access="permitAll" />
<security:intercept-url pattern="/login" access="permitAll" />
<security:intercept-url pattern="/login/forgot" access="permitAll" />
<security:intercept-url pattern="/login/resetpassword" access="permitAll" />
<security:intercept-url pattern="/home/admin/**" access="hasAnyRole('ROLE_admin', 'ROLE_manager')" />
<security:intercept-url pattern="/**" access="hasAnyRole('ROLE_admin', 'ROLE_manager','ROLE_user')" />
<security:form-login
login-page="/login"
login-processing-url="/login"
authentication-failure-handler-ref="authenticationFailureFilter"
authentication-success-handler-ref="authenticationSuccessHandler"
username-parameter="email"
password-parameter="password" />
<!-- enable csrf protection -->
<security:csrf/>
</security:http>
Is there any problem with my web.xml or Spring Security?
Please set the max age attribute of the cookie.
By default, -1 is returned, which indicates that the cookie will
persist until browser shutdown.
Http Servlet Cookie Max Age
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 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" />
I have a spring 3 application with the configurations given below. When any user tries to access a page and he/she isn't logged in, I get an Access is Denied exception with an ugly stack trace. How do I handle this exception and not let it dump out a stack trace. I implemented my own access-denied-handler but that doesn't get invoked.
Based on the type of the requested resource, I would like to show custom error messages or pages. Here is my spring configuration.
How do I get Spring to invoke my access-denied-handler . Here is my spring configuration
<security:http auto-config='true'>
<security:intercept-url pattern="/static/**" filters="none"/>
<security:intercept-url pattern="/login" filters="none"/>
<security:intercept-url pattern="/**" access="ROLE_USER" />
<security:form-login login-page="/index"
default-target-url="/home" always-use-default-target="true"
authentication-success-handler-ref="AuthenticationSuccessHandler"
login-processing-url="/j_spring_security_check"
authentication-failure-url="/index?error=true"/>
<security:remember-me key="myLongSecretCookieKey" token-validity-seconds="1296000"
data-source-ref="jdbcDataSource" user-service-ref="AppUserDetailsService" />
<security:access-denied-handler ref="myAccessDeniedHandler" />
</security:http>
<bean id="myAccessDeniedHandler"
class="web.exceptions.handlers.AccessDeniedExceptionHandler">
<property name="errorPage" value="/public/403.htm" />
</bean>
The custom class for handling this exception is given below
public class AccessDeniedExceptionHandler implements AccessDeniedHandler
{
private String errorPage;
#Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException arg2) throws IOException, ServletException {
response.sendRedirect(errorPage);
}
public void setErrorPage(String errorPage) {
if ((errorPage != null) && !errorPage.startsWith("/")) {
throw new IllegalArgumentException("errorPage must begin with '/'");
}
this.errorPage = errorPage;
}
}
When I run this application, this is the error that I get. I am only pasting a part of the stacktrace and the Spring Debug logs.
20:39:46,173 DEBUG AffirmativeBased:53 - Voter: org.springframework.security.access.vote.RoleVoter#5b7da0d1, returned: -1
20:39:46,173 DEBUG AffirmativeBased:53 - Voter: org.springframework.security.access.vote.AuthenticatedVoter#14c92844, returned: 0
20:39:46,178 DEBUG ExceptionTranslationFilter:154 - Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:71)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:204)
How do I fix this problem? Firstly, I want to stop spring from Throwing that exception. If it still throws it, I want to handle it and not raise any flags.
Update: I have attached a part of my web.xml as well.
<!-- Hibernate filter configuration -->
<filter>
<filter-name>HibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--Dispatcher Servlet -->
<servlet>
<servlet-name>rowz</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
In your configuration You require the user to be always authenticated when entering any URL on Your site:
<security:intercept-url pattern="/**" access="ROLE_USER" />
I think You should allow the user to be unauthenticated when entering the login page:
<security:intercept-url pattern="/your-login-page-url" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/your-login-process-url" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/your-login-failure-url" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/**" access="ROLE_USER" />
If You use URL's like: /login/start, /login/error and /login/failure You can have:
<security:intercept-url pattern="/login/**" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/**" access="ROLE_USER" />
Update:
Having this configuration should make the framework to redirect all unauthenticated (anonymous) users to login page, and all authenticated to AccessDeniedHandler. The AccessDeniedException is one of the core parts of the framework and ignoring it is not a good idea. It's hard to help more if You only provide parts of Your Spring Security configuration.
Be sure to read the JavaDoc for ExceptionTranslationFilter for detailed explanation of what exceptions are thrown by the framework, why and how are the handled by default.
If possible, try removing as many custom parts You added, like AuthenticationSuccessHandler, RememberMeAuthenticationFilter and AccessDeniedHandler and see if the problem pesist? Try to get the minimal congiuration and add new features step by step to see where the error comes from.
One important thing that You don't mention in Your question is what is the result of this error message? Do You get HTTP 500? Or HTTP 403? Or do You get redirected to login page?
If, as You mentioned in the question, the user is unauthenticated and he/she gets redirected to login page, than that's how it's intended to work. It looks like You get the error message logged by ExceptionTranslationFilter:172 only because You have DEBUG level set to Spring Security classes. If so, than that's also how it's intended to work, and if You don't want the error logged, than simply rise the logging level for Spring Secyruty classes.
Update 2:
The patterns with filters="none" must match the login-page, login-processing-url and authentication-failure-ur attributes set in <security:form-login /> to skip all SpringSecurity checks on pages that display the login page and process the logging in.
<security:http auto-config='true'>
<security:intercept-url pattern="/static/**" filters="none"/>
<security:intercept-url pattern="/index" filters="none"/>
<security:intercept-url pattern="/j_spring_security_check" filters="none"/>
<security:intercept-url pattern="/**" access="ROLE_USER" />
<security:form-login login-page="/index"
default-target-url="/home" always-use-default-target="true"
authentication-success-handler-ref="AuthenticationSuccessHandler"
login-processing-url="/j_spring_security_check"
authentication-failure-url="/index?error=true"/>
<security:remember-me key="myLongSecretCookieKey" token-validity-seconds="1296000"
data-source-ref="jdbcDataSource" user-service-ref="AppUserDetailsService" />
<security:access-denied-handler ref="myAccessDeniedHandler" />
</security:http>
AccessDeniedHandler is invoked when user is logged in and there is no permissions to resource (source here). If you want to handle request for login page when user is not logged in, just configure in security-context:
<http ... entry-point-ref="customAuthenticationEntryPoint">
And define customAuthenticationEntryPoint:
<beans:bean id="customAuthenticationEntryPoint" class="pl.wsiadamy.webapp.controller.util.CustomAuthenticationEntryPoint">
</beans:bean>
TIP, don't try to fight with ExceptionTranslationFilter.
I have tried to override org.springframework.security.web.access.ExceptionTranslationFilter, without effects:
<beans:bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<beans:property name="authenticationEntryPoint" ref="customAuthenticationEntryPoint"/>
<beans:property name="accessDeniedHandler" ref="accessDeniedHandler"/>
</beans:bean>
<beans:bean id="accessDeniedHandler"
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<beans:property name="errorPage" value="/accessDenied.htm"/>
</beans:bean>
The ref="customAuthenticationEntryPoint" just didn't invoked.
I have added Spring Access denied page in follwing way:
Spring Frame Work: 3.1
Spring Security: 3.1, Java 1.5+
Entry in *-security.xml:
<security:access-denied-handler error-page="/<My Any error page controller name>" />
Example:
<security:access-denied-handler error-page="/accessDeniedPage.htm" />
Error page will always start with "/"
Entry for controller:
#Controller
public class RedirectAccessDenied {
#RequestMapping(value = "/accessDeniedPage.htm", method = RequestMethod.GET)
public String redirectAccessDenied(Model model) throws IOException, ServletException {
System.out.println("############### Redirect Access Denied Handler!");
return "403";
}
}
Here 403 is my JSP name.
Spring Security uses an AuthenticationEntryPoint object to decide what to do when a user requires authentication. You can create your own AuthenticationEntryPoint bean ( see javadoc ), and then set the entryPoint attribute in the http element:
<http entry-point-ref="entryPointBean" .... />
However, by default, the form-login element creates a LoginUrlAuthenticationEntryPoint which redirects all of your unauthenticated users to the login page, so you shouldn't have to do this yourself. In fact, the log you posted claims it is forwarding the user to the authentication entry point: "Access is denied (user is anonymous); redirecting to authentication entry point".
I wonder if the problem is that you turned off the filter chain for the login url. Instead of setting filters to none, which means spring security is bypassed entirely, try keeping the filters on but allowing unrestricted access like this:
<security:intercept-url pattern="/login" access="permitAll" />
If that still doesn't help, please post the rest of the log so we can see what happens after the request is transferred to the entry point.
Programmatically solution:
#Order(1)
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//
// ...
//
#Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandlerImpl() {
#Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
super.handle(request, response, accessDeniedException);
accessDeniedException.printStackTrace();
}
});
//
// ...
//
}
}
Can you check your web.xml is supporting forward request?
errorPage is a FORWARD request and mostly in web.xml we support REDIRECTS only. Just a thought else your code looks ok to me.
Edited
A different point of view and This is been taken from working code only.
Have a look at Authenticated Voter class
Disable the annotations
<global-method-security pre-post-annotations="disabled"
secured-annotations="disabled" access-decision-manager-ref="accessDecisionManager">
</global-method-security>
bypassing filters
<http auto-config="true" use-expressions="true"
access-decision-manager-ref="accessDecisionManager"
access-denied-page="/accessDenied">
<intercept-url pattern="/appsecurity/login.jsp" filters="none" />
<intercept-url pattern="/changePassword" filters="none" />
<intercept-url pattern="/pageNotFound" filters="none" />
<intercept-url pattern="/accessDenied" filters="none" />
<intercept-url pattern="/forgotPassword" filters="none" />
<intercept-url pattern="/**" filters="none" />
<form-login login-processing-url="/j_spring_security_check"
default-target-url="/home" login-page="/loginDetails"
authentication-failure-handler-ref="authenticationExceptionHandler"
authentication-failure-url="/?login_error=t" />
<logout logout-url="/j_spring_security_logout"
invalidate-session="true" logout-success-url="/" />
<remember-me />
<!-- Uncomment to limit the number of sessions a user can have -->
<session-management invalid-session-url="/">
<concurrency-control max-sessions="1"
error-if-maximum-exceeded="true" />
</session-management>
</http>
custom Decision Voter
<bean id="customVoter" class="xyz.appsecurity.helper.CustomDecisionVoter" />
Access Decision Manager
<!-- Define AccessDesisionManager as UnanimousBased -->
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<property name="decisionVoters">
<list>
<ref bean="customVoter" />
<!-- <bean class="org.springframework.security.access.vote.RoleVoter"
/> -->
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</property>
</bean>
Authentiation Exception Handler
<bean id="authenticationExceptionHandler"
class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<property name="exceptionMappings">
<props>
<!-- /error.jsp -->
<prop
key="org.springframework.security.authentication.BadCredentialsException">/?login_error=t</prop>
<!-- /getnewpassword.jsp -->
<prop
key="org.springframework.security.authentication.CredentialsExpiredException">/changePassword</prop>
<!-- /lockedoutpage.jsp -->
<prop key="org.springframework.security.authentication.LockedException">/?login_error=t</prop>
<!-- /unauthorizeduser.jsp -->
<prop
key="org.springframework.security.authentication.DisabledException">/?login_error=t</prop>
</props>
</property>
</bean>
It looks like spring tries to redirect users who have not logged in to the login page, which is "/index", but that itself is a protected url.
The other possibility is, it tries to display /public/403.html, but that is again protected by security configuration.
Can you add the following entries and try?
<security:intercept-url pattern="/login" filters="none" />
<security:intercept-url pattern="/public/**" filters="none" />