spring authentication: can't logout - spring

I'm new to Spring. I can't logout with spring security.
Login works fine, and I'm following this post to implement the logout function.
but I can't make it work.
here's my spring-security.xml:
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/index" access="hasRole('ROLE_USER')" />
<security:logout logout-success-url="/index" logout-url="/logout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="matt3o" password="secret" authorities="ROLE_USER" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
and here's my index.jsp:
<c:if test="${pageContext.request.userPrincipal.name != null}">
<h2>Welcome : ${pageContext.request.userPrincipal.name}
</c:if>
<p>Logout</p>
Please can somebody explain to me how loggin/loggout works and why my logout doesn't ?
In index.jsp I'm trying to logout in different ways, none of them works:
<!--1-->
<c:url value="/logout" var="logoutUrl" />
<form id="logout" action="${logoutUrl}" method="post" >
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
<c:if test="${pageContext.request.userPrincipal.name != null}">
Logout
</c:if>
<br><br>
<!--2-->
logout1
<br><br>
<!--3-->
<a href='<c:url value="j_spring_security_logout" />'>logout</a>

Spring Security 4 requires a POST request to logout instead of a GET. Next to that by default it is secured using a CSFR token, which you would need to add to the form (see the javadoc).
So instead of a link use a form to invoke the logout.
<c:url var="logoutUrl" value="/logout"/>
<form action="${logoutUrl}" method="post">
<input type="submit" value="Log out" />
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
or when using the security tag library
<c:url var="logoutUrl" value="/logout"/>
<form action="${logoutUrl}" method="post">
<input type="submit" value="Log out" />
<sec:csrfInput />
</form>
See also here and here in the reference guide.
If you want to use a GET either configure the logout functionality as such that it supports GET requests (for this you need to provide an ant matcher) or by disabling CSFR which can be done by adding <sec:csfr disabled="true" /> to your xml configuration.

you can use
href="<c:url value="/logout"/>"

Related

Spring security redirecting to login page for authenticated urls

I am new to spring. I am creating a spring mvc app. I have a admin url "/admin/".If I login with user credentials with ROLE_ADMIN then I can access the admin page. Right now this scenario is working fine. But If I have not logged in with ROLE_ADMIN and I try to access /admin/ url spring security is redirecting me to /login page.
Here what I want to not expose to outer world that /admin/(or admin url exists) url need authentication. And I want to show default exception page or home page if someone who is not authorized try to access /admin/ url.
Also I need to have custom "/login" url like "/custom_url/" instead of "/login"
But right now I don't have any idea how to achieve this. Any help is appreciated.
applicationContext.xml
</bean>
<security:http auto-config="true">
<security:intercept-url pattern="/admin/**"
access="hasRole('ROLE_ADMIN')" />
<security:form-login
login-page="/login"
default-target-url="/admin"
always-use-default-target="true"
login-processing-url="/j_spring_security_check"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password" />
<security:logout logout-success-url="/" invalidate-session="true" logout-
url="/logout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:jdbc-user-service data-source-ref="dataSource"
authorities-by-username-query="SELECT
username, authority From authorities WHERE username = ?"
users-by-username-query="SELECT
username, password, enabled FROM users WHERE username = ?" />
</security:authentication-provider>
</security:authentication-manager>
Login Controller
#RequestMapping("/login")
public String login(#RequestParam(value="error", required = false) String
error, #RequestParam(value="logout",
required = false) String logout, Model model) {
if (error!=null) {
model.addAttribute("error", "Invalid username and password");
}
if(logout!=null) {
model.addAttribute("msg", "You have been logged out successfully.");
}
return "login";
}
login.jsp
<c:if test="${not empty msg}">
<div class="msg">${msg}</div>
</c:if>
<form name="loginForm" action="<c:url
value="/j_spring_security_check" />" method="post">
<c:if test="${not empty error}">
<div class="error" style="color: #ff0000;">${error}</div>
</c:if>
<div class="form-group">
<label for="username">User: </label>
<input type="text" id="username" name="username"
class="form-control" />
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" id="password" name="password"
class="form-control" />
</div>
<input type="submit" value="Submit" class="btn btn-default">
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
</form>
I am using Spring security 4.
Change the authentication-failure-url="/login?error" to authentication-failure-url="/". This will redirect you to Home page.
The correct xml-snippet in applicationContext.xml is as following:
<security:form-login
login-page="/login"
default-target-url="/admin"
always-use-default-target="true"
login-processing-url="/j_spring_security_check"
authentication-failure-url="/"
username-parameter="username"
password-parameter="password" />
Note: You can change value of authentication-failure-url attribute to an exception page as per need.

Spring 4 mvc login intercepting

I am new at Spring mvc. I am working on a webpage on which users will be able to log in after they have registered and activated themselves.
I sucessfully implemented the Login part, it works fine.
I would like to check if the user has already activated his/her accout via email before the login process launches. Is it possible?
I have tried to solve it with a Login interceptor, but it seems the default "/j_spring_security_check" can not be intercepted. Except this link the interceptor works with all of the url-s.
Is it possible to intercept this default link?
My spring-security.xml
...
<http use-expressions="true">
<intercept-url pattern="/admin**" access="hasRole('ADMIN')" />
<access-denied-handler error-page="/403" />
<form-login login-page="/login"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password"/>
<logout logout-success-url="/login?logout" />
<!--enable csrf protection-->
<csrf />
</http>
<authentication-manager>
<authentication-provider user-service-ref="loginService" />
</authentication-manager>
LoginService
#Service("loginService")
public class LoginServiceImpl implements UserDetailsService {
//It is a regular UserDetailsService nothing extra stuff and works fine
...
}
Login.jsp
....
<div id="login-box">
<span style="color: red">${message}</span>
<c:url value="/j_spring_security_check" var="loginUrl"/>
<form name='f' action="${loginUrl}" method="post">
<p>
<label for="username">Email</label>
<input type="text" id="username" name="username"/>
</p>
<p>
<label for="password">Password</label>
<input type="password" id="password" name="password"/>
</p>
<input type="hidden"
name="${_csrf.parameterName}"
value="${_csrf.token}"/>
<button type="submit" class="btn">Log in</button>
</form>
</div>
...
mvc-dispatcher-servlet.xml
...
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/j_spring_security_check"/>
<bean id="logininterceptor" class="org.psi.controller.LoginInterCeptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
...
LoginInterceptor
public class LoginInterCeptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
//Do some check
System.out.println("some check");
return true;
}
}
Any other possible solution are welcome.
I would accomplish this by using either the locked or enabled property on the UserDetails object and let Spring handle the rest rather than trying to intercept the request. When the user confirms their email via the link you send them, flip the flag in the database to indicate the the user is either enabled or not locked.
Alternatively, if you really want to go the intercept route, what I might do is have the login form point to something other than j_spring_security_check, intercept whatever that is, and then (if desired) forward the request to j_spring_security_check. I'm not sure if you can actually override that url.

How To Configure /oauth/token ModelAndView in Spring

I successfully configured an oauth spring application. However, my headache is how to make it return to the login page with a successful token; The log shows the following entry:
`DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'dispatcher': assuming HandlerAdapter completed request handling`
Here is my login page:
` <c:url value="/oauth/token" var="loginProcessingUrl"/>
<form:form action="${loginProcessingUrl}" method="post">
<fieldset>
<legend>Please Login</legend>
<!-- use param.error assuming FormLoginConfigurer#failureUrl contains the query parameter error -->
<c:if test="${param.error != null}">
<div>
Failed to login.
<c:if test="${SPRING_SECURITY_LAST_EXCEPTION != null}">
Reason: <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
</c:if>
</div>
</c:if>
<!-- the configured LogoutConfigurer#logoutSuccessUrl is /login?logout and contains the query param logout -->
<c:if test="${param.logout != null}">
<div>
You have been logged out.
</div>
</c:if>
<c:if test="${param.success != null}">
<div>
You have been successfully been authenticated.
</div>
</c:if>
<p>
<label for="username">Username</label>
<input type="text" id="username" name="username"/>
</p>
<p>
<label for="password">Password</label>
<input type="password" id="password" name="password"/>
</p>
<!-- if using RememberMeConfigurer make sure remember-me matches RememberMeConfigurer#rememberMeParameter -->
<p>
<label for="remember-me">Remember Me?</label>
<input type="checkbox" id="remember-me" name="remember-me"/>
<input type="hidden" id="client_id" name="client_id" value="11111111"/>
<input type="hidden" id="client_secret" name="client_secret" value="2222222"/>
<input type="hidden" id="grant_type" name="grant_type" value="password"/>
<input type="hidden" id="response_type" name="response_type" value="token"/>
<input type="hidden" id="redirect_uri" name="redirect_uri" value="/login?success=1"/>
</p>
<div>
<button type="submit" class="btn">Log in</button>
</div>
</fieldset>
`
And here's my spring-security.xml file:
`<http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER"/>
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>`
Why can't I go back to the login page once a token is successfully issued. Any help is appreciated.
Thanks

spring security bad credentials even though they are correct

I am using Spring Roo and I setup my Spring Security like this (applicationContext-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-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- HTTP security configurations -->
<http auto-config="true" use-expressions="true" request-matcher="regex">
<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" />
<intercept-url pattern="\A/hotels\?form.*\Z" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/**" access="permitAll"/>
</http>
<!-- Configure Authentication mechanism -->
<authentication-manager alias="authenticationManager">
<!-- SHA-256 values can be produced using 'echo -n your_desired_password | sha256sum' (using normal *nix environments) -->
<authentication-provider>
<password-encoder hash="sha-256">
<!-- <salt-source user-property="login"/> -->
</password-encoder>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="
SELECT login, password, enabled
FROM user WHERE login = ?"
authorities-by-username-query="
FROM user u, role r,
user_role ur
WHERE u.id = ur.user
AND r.id = ur.role
AND u.login = ?"
/>
<user-service>
<user name="admin" password="8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918" authorities="ROLE_ADMIN" />
<user name="user" password="04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
Then I created a dummy user with the login johnny and the password admin, which is stored in the database like this 8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918.
This is the default login page provided by the framework:
<div xmlns:spring="http://www.springframework.org/tags" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:util="urn:jsptagdir:/WEB-INF/tags/util" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
<jsp:directive.page contentType="text/html;charset=UTF-8" />
<jsp:output omit-xml-declaration="yes" />
<spring:message code="security_login_title" var="title" htmlEscape="false" />
<util:panel id="title" title="${title}">
<c:if test="${not empty param.login_error}">
<div class="errors">
<p>
<spring:message code="security_login_unsuccessful" />
<c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
.
</p>
</div>
<br/>
</c:if>
<c:if test="${empty param.login_error}">
<p>
<!-- <spring:message code="security_login_message" /> -->
</p>
</c:if>
<spring:url value="/resources/j_spring_security_check" var="form_url" />
<form name="f" action="${fn:escapeXml(form_url)}" method="POST">
<input type="hidden" name="test"/>
<div>
<label for="j_username">
<spring:message code="security_login_form_name" />
</label>
<input id="j_username" type='text' name='j_username' style="width:150px" />
<spring:message code="security_login_form_name_message" var="name_msg" htmlEscape="false" />
<script type="text/javascript">
<c:set var="sec_name_msg">
<spring:escapeBody javaScriptEscape="true">${name_msg}</spring:escapeBody>
</c:set>
Spring.addDecoration(new Spring.ElementDecoration({elementId : "j_username", widgetType : "dijit.form.ValidationTextBox", widgetAttrs : {promptMessage: "${sec_name_msg}", required : true}}));
</script>
</div>
<br />
<div>
<label for="j_password">
<spring:message code="security_login_form_password" />
</label>
<input id="j_password" type='password' name='j_password' style="width:150px" />
<spring:message code="security_login_form_password_message" var="pwd_msg" htmlEscape="false" />
<script type="text/javascript">
<c:set var="sec_pwd_msg">
<spring:escapeBody javaScriptEscape="true">${pwd_msg}</spring:escapeBody>
</c:set>
Spring.addDecoration(new Spring.ElementDecoration({elementId : "j_password", widgetType : "dijit.form.ValidationTextBox", widgetAttrs : {promptMessage: "${sec_pwd_msg}", required : true}}));
</script>
</div>
<br />
<div class="submit">
<script type="text/javascript">Spring.addDecoration(new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));</script>
<spring:message code="button_submit" var="submit_label" htmlEscape="false" />
<input id="proceed" type="submit" value="${fn:escapeXml(submit_label)}" />
<spring:message code="button_reset" var="reset_label" htmlEscape="false" />
<input id="reset" type="reset" value="${fn:escapeXml(reset_label)}" />
</div>
</form>
</util:panel>
</div>
However, when I try to log in I get a Bad credentials error. What is happening?
I can't really manage to find a way of how to debug this because it's all happening internally in spring security I guess so I can't get to know what queries are actually being made and I can't/don't know where to look to figure out why this is failing.
Look at the debug log output when you try to authenticate as the user (always a good idea). Most likely it says it can't find the user "johnny".
This is most likely because you have both a jdbc-user-service and a user-service in the same authentication-provider which won't work.
Use two separate authentication-provider elements:
<authentication-provider>
<jdbc-user-service ... />
</authentication-provider>
<authentication-provider>
<user-service>
....
</user-service>
</authentication-provider>
Also, as I said in your other question, you shouldn't use SHA as a password hashing algorithm unless it's for a legacy system.
After more suffering I managed to solve it. I made the user and role entities-tables again and re-wrote the queries:
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT u.login, u.password, u.enabled from users u where u.login=?"
authorities-by-username-query="SELECT u.login, r.name FROM users u left join user_roles ur on u.id=ur.user join roles r on ur.roles=r.id WHERE u.login=?"
/>
Using two separte authentication-provide had nothing to do with my error.

How to display error message in my JSP page using spring security 2.0

Hi I am now using spring security. It works fine. But if login failed, no error message display. I am wondering how can I display error message?
I have configured the ResourceBundleMessageSource in my applicationContext.xml
<!-- Spring security error message config -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>messages</value>
</list>
</property>
</bean>
And my security-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:David="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<David:http auto-config="true" access-denied-page="/accessDenied.html">
<!-- Don`t set any role restriction on login.jsp -->
<David:intercept-url pattern="/login.jsp"
access="IS_AUTHENTICATED_ANONYMOUSLY" />
<!-- Restrict access to All other pages -->
<David:intercept-url pattern="/admin.jsp"
access="ROLE_ADMIN" />
<!-- Set the login page and what to do if login fails -->
<David:form-login login-page="/login.jsp"
default-target-url="/"/>
<David:logout logout-success-url="/" />
</David:http>
<!-- Specify login examnination strategy -->
<David:authentication-provider>
<David:password-encoder hash="md5" />
<David:jdbc-user-service
data-source-ref="dataSource"
users-by-username-query="select username, password, status as enabled from user where username=?"
authorities-by-username-query="select u.username,r.name as authority
from user u
join user_role ur
on u.id=ur.user_id
join role r
on r.id=ur.role_id
where u.username=?" />
</David:authentication-provider>
</beans>
My jsp page:
<%# page contentType="text/html;charset=utf-8"%>
<%# taglib prefix="s" uri="/struts-tags"%>
<%# page
import="org.springframework.security.ui.AbstractProcessingFilter"%>
<%# page
import="org.springframework.security.ui.webapp.AuthenticationProcessingFilter"%>
<%# page import="org.springframework.security.AuthenticationException"%>
<form id="myform" class="cmxform" method="post"
action="${pageContext.request.contextPath}/j_spring_security_check">
<fieldset>
<legend>
Please input correct username and password to login
</legend>
<p>
<label for="user">
Username:
</label>
<input id="user" name="j_username" />
</p>
<p>
<label for="pass">
Password:
</label>
<input type="password" name="j_password" id="password" />
</p>
<p>
<input type="submit" class="submit" value="Login" />
</p>
</fieldset>
</form>
Any suggestions? Any help will be appreciated.
<c:if test="${not empty param.login_error}">
<div class="error">
Your login attempt was not successful, try again.<br />
Reason: #{sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}
</div>
</c:if>
This works
<c:if test="${param.error != null}">
Error
</c:if>
Where is the jsp to actually display the error? Something like
<c:if test="${not empty param.error}">
<!-- Display error message -->
</c:if>
If you want to customize this message, you should also look at this
Maybe you can try this...put
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
for c tag on jsp page, and then put something like below for error msg display
<c:when test="${param.error == 1}">
<h3 style="font-size:20; color:#FF1C19;">Wrong id or password!</h3>
</c:when>
"param.error == 1" can get return value from Spring Security(security-config.xml) like
<beans:bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<beans:property name="exceptionMappings">
<beans:props>
<beans:prop key="org.springframework.security.core.userdetails.UsernameNotFoundException">/login.action?error=1</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
This worked for me :
<c:if test="${not empty sessionScope.SPRING_SECURITY_LAST_EXCEPTION}">
<div class="error">
Your login attempt was not successful, try again.<br />
Reason: ${sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}
</div>
</c:if>
I am using spring-security v 4.0.3.RELEASE
Using the not empty did not work for me. However checking for null worked for me.
<c:if test="${ param.error ne null}">
Display error message
</c:if>

Resources