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
}
}
Hello Stackoverflower,
i've got a Issue with the Spring Security stuff. The Login Box that should appear before you can proceed to your application dont appear and i can access to my application without any authentication. I dont have any clue why this happen.
It would be very important to know why no User and Password are asked.
I test my app with the RESTCLient Add on for firefox.
The important entry in the web.xml looks like:
<!-- Security Configuration -->
<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>
<!-- Spring Json Init -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>json</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>json</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
My spring-security is:
<!-- Security Propertie Configuration -->
<security:http use-expressions="true">
<security:http-basic/>
</security:http>
<security:authentication-manager>
<security:authentication-provider
ref="springUserService" />
</security:authentication-manager>
The springUserService looks like this:
#Component
public class springUserService implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
String name = authentication.getName();
String password = authentication.getCredentials().toString();
List<GrantedAuthority> grantedAuths = new ArrayList<>();
return new UsernamePasswordAuthenticationToken(name, password, grantedAuths);
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
Im very thankfull for every Hint or answer.
I think you need to add some intercept url tag in your spring security config:
<security:intercept-url pattern="/securedUrl" access="isAuthenticated()" />
<security:intercept-url pattern="/login" access="permitAll" />
So change your code in something like this:
<security:http use-expressions="true">
<security:intercept-url pattern="/securedUrl" access="isAuthenticated()" />
<security:intercept-url pattern="/login" access="permitAll" />
</security:http>
You can also use wildcard in pattern-attribute or custom access evaluation:
<intercept-url pattern="/url1/**" access="hasAnyRole('ROLE_ADMIN', 'ROLE_USER')"/>
<intercept-url pattern="/url2/**" access="isAuthenticated()" />
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/**" access="permitAll" />
Try this:
<security:http auto-config="true" use-expressions="true" path-type="regex">
<security:intercept-url pattern="/admin/.*" access="hasRole('ROLE_ADMIN')" />
<security:intercept-url pattern="/.*" access="isAuthenticated()" />
</security:http>
Here is a more detailed example with explanations:
<http auto-config="true" use-expressions="true" path-type="regex">
<form-login
password-parameter="password" -- password field name in your form
username-parameter="username" -- username field name in your form
login-processing-url="/security/j_spring_security_check" -- where your login form should submit to, no need to map this to anything, Spring Security handles it
login-page="/login" -- where you'll be taken to when not logged in
authentication-failure-url="/login?login_error=t" -- if your login fails, security will redirect you with login_error set to t
default-target-url="/router" -- if you want to route people based on roles, etc, you can map a controller ot this URL
always-use-default-target="false" -- this will send logged in users to your router URL
/>
<headers>
<xss-protection/> -- inserts header to prevent prevents cross site scripting
</headers>
<logout logout-url="/security/j_spring_security_logout" /> -- logout url, no need ot map it to anything, handled by Spring Security
<intercept-url pattern="/admin/.*" access="hasRole('ROLE_ADMIN')" /> -- security URLs by roles
<intercept-url pattern="/register" access="permitAll"/> -- let new users register by allowing everyone access to the registration page
<intercept-url pattern="/.*" access="isAuthenticated()" requires-channel="https" /> -- require users to be authenticated for the rest of the page and require HTTPS (optional) for ALL urls
</http>
I am new to Spring and Spring-Security. I have been going through the tutorials
here
The user are not allowed to hit add employee page without login. So if you hit add employee page, you will be directed to the login page and when login succeeded you are directed to the add employee page automatically.
But once the user logged in add employee link can be accessed even after the user logs out. It can be accessed even after the server is restarted, I had to close the browser window for the login credentials to be destroyed.
It works fine when when I keep the logout url as "j_spring_security_logout" which I dont want to use. I want to use custom feild names and urls, is it possible?
This is how my spring-security.xml looks
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/logout" access="permitAll" />
<intercept-url pattern="/accessdenied" access="permitAll" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<form-login login-page="/login" default-target-url="/list"
authentication-failure-url="/accessdenied" />
<logout logout-success-url="/logout" invalidate-session="true"
delete-cookies="true" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="hasif" password="password" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
This is how my LoginController looks
#Controller
public class LoginController {
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login() {
return "login";
}
#RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout(HttpServletRequest request) {
HttpSession session = request.getSession(false);
session.invalidate();
return "logout";
}
#RequestMapping(value = "/accessdenied", method = RequestMethod.GET)
public String accessdenied() {
return "accessdenied";
}
}
Your configuration is wrong, you must specify the logout-url attribute and not the logout-success-url. The latter is the url you are send to after logout has been successful.
<logout logout-url="/logout" invalidate-session="true" delete-cookies="true" />
delete-cookies takes a comma separated string with names of cookies to delete, I doubt you have a cookie named true and the session is invalidated by default. So basically the following gives the same result.
<logout logout-url="/logout" />
If you want to change the name of the parameter to use for specifying the username/password add respectively the username-parameter and password-parameter on the form-login element.
<form-login login-page="/login" default-target-url="/list" authentication-failure-url="/accessdenied" username-parameter="my-username-param" password-parameter="my-password-param"/>
For an explanation of the namespaces I suggest a read of the reference guide.
First Why do you want to do manually when Spring provide such a good security feature.
No doubt you can handle it by your self. For this you have to just invalidate the current session when user click on Log out button or link. There is method available HttpSession#invalidate() which can solve your problem.
After successful login i want to proceed with further request processing with new url. But the url is invoking exposed service in spring mvc where security configuration doesn't check the session authentication for coming url.Please take a look below code.
<http auto-config="true" use-expressions="true">
<!-- <intercept-url pattern="/**" access="isAuthenticated()" /> -->
<intercept-url pattern="/home*" access="isAuthenticated()" />
<intercept-url pattern="/admin*" access="isAuthenticated()" />
<form-login login-page="/" default-target-url="/home"
authentication-failure-url="/accessdenied" always-use-default-target="false"/>
<logout logout-success-url="/" />
<anonymous username="guest" granted-authority="ROLE_GUEST" />
<session-management invalid-session-url="/" session-authentication-error-url="/login.jsp?error=alreadyLogin">
<concurrency-control max-sessions="1" expired-url="/login.jsp?error=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false"/>
</session-management>
<remember-me />
</http>
When jsp page submits login authentication J_security_check the target url invoked which subsequently calls interceptor pattern /home* and authenticates the login credentials.
if i'm calling the exposed service before login "/address/userid/" it directly invokes the service method how to make it session bound, if session exist get the data otherwise not.
how different spring security session from http session,how to maintain spring security session like http session in spring mvc.
if i'm adding <intercept-url pattern="/**" access="isAuthenticated()" /> it doesn't work, it doesn't show login jsp as well.Where i am doing wrong please clarify.
How to distinguish userid/pwd in authentication manager as per given below, as single ? takes first parameter.
<authentication-manager>
<authentication-provider>
<!-- <user-service> <user name="admin" password="secret" authorities="ROLE_ADMIN,ROLE_USER"/>
</user-service> -->
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT USER_NAME,USER_PWD, 'true' as enabled from LOGIN_USER where USER_NAME=?"
authorities-by-username-query="select LOGIN_USER.USER_NAME , LOGIN_USER.ROLE_ID as authorities from LOGIN_USER
where LOGIN_USER.USER_NAME =?" />
</authentication-provider>
</authentication-manager>
I have come across few sites it describes only login spring security session management.i couldn't get clarity.Thanks in advance.
i implemented using interceptor handler to check URI & session attributes which works fine but looking for better options in spring framework.
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" />