3

I am using spring mvc + security to build a simple web app and currently having issues with the login. I am not able to exclude the login page from the spring security if i want to secure /** (everything basically). This is how my config look like:

spring.security.xml

    <http pattern="/login" security="none"/>
    <http pattern="/view_register.htm" security="none"/>
    <http>
        <intercept-url pattern="/**" access="ROLE_USER" />
        <form-login login-page="/login" default-target-url="/game" authentication-failure-url="/failedlogin" />
        <logout logout-success-url="/login" />
</http>

LoginController

@Controller
public class LoginLogoutController {

  @RequestMapping(value="/login", method = RequestMethod.GET)
  public String login(ModelMap model) {

    return "login";
  }

  @RequestMapping(value="/failedlogin", method = RequestMethod.GET)
  public String loginerror(ModelMap model) {

    model.addAttribute("error", "true");
    return "login";
  }

}

login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Login Page</title>
<style>
.errorblock {
    color: #ff0000;
    background-color: #ffEEEE;
    border: 3px solid #ff0000;
    padding: 8px;
    margin: 16px;
}
</style>
</head>
<body onload='document.f.j_username.focus();'>
    <h3>Login with Username and Password (Custom Page)</h3>

    <c:if test="${not empty error}">
        <div class="errorblock">
            Your login attempt was not successful, try again.<br /> Caused :
            ${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
        </div>
    </c:if>

    <form name='f' action="<c:url value='j_spring_security_check' />"
        method='POST'>

        <table>
            <tr>
                <td>User:</td>
                <td><input type='text' name='j_username' value=''>
                </td>
            </tr>
            <tr>
                <td>Password:</td>
                <td><input type='password' name='j_password' />
                </td>
            </tr>
            <tr>
                <td colspan='2'><input name="submit" type="submit"
                    value="submit" />
                </td>
            </tr>
            <tr>
                <td>Don't have an account yet.</td>
                <td> <a href="<c:url value="view_register.htm" />" > Register here</a>
                </td>
            </tr>
        </table>

    </form>
</body>
</html>

I want to secure the whole app and exlude the login and the registration page. With my current config the whole security behaves very strangly. If i enter wrong credentials the

 @RequestMapping(value="/login", method = RequestMethod.GET)
  public String login(ModelMap model) {

is called and from the other hand if i enter the correct username/pass the login failed controller method is called.

Found out that if i modify the

 <intercept-url pattern="/**" access="ROLE_USER" />

to

<intercept-url pattern="/game*" access="ROLE_USER" />

and remove the

<http pattern="/login" security="none"/>

everything is working as expected. Its very strange and can't really figure out why this is happening.

EDIT

Just created a tiny version of my sample project (maven) and uploaded to: fileswap. Any help or suggestion will be really cool as i am still confused.

shippi
  • 2,344
  • 7
  • 22
  • 28

2 Answers2

2

Try to insert these lines:

<intercept-url pattern="/login/**" access="ROLE_ANONYMOUS,ROLE_USER" />
<intercept-url pattern="/failedlogin/**" access="ROLE_ANONYMOUS,ROLE_USER" />
<intercept-url pattern="/view_register/**" access="ROLE_ANONYMOUS,ROLE_USER" />

after <http>, and add auto-config="true" inside <http>:

<http auto-config="true">

    <intercept-url pattern="/login/**" access="ROLE_ANONYMOUS,ROLE_USER" />
    <intercept-url pattern="/failedlogin/**" access="ROLE_ANONYMOUS,ROLE_USER" />
    <intercept-url pattern="/view_register/**" access="ROLE_ANONYMOUS,ROLE_USER" />

    <intercept-url pattern="/**" access="ROLE_USER" />

    <form-login login-page="/login" default-target-url="/game" authentication-failure-url="/failedlogin" />
    <logout logout-success-url="/login" />
</http>

and remove:

<http pattern="/login" security="none"/>

I do not know what this line is for, but it should work without it.

See the Spring Security Reference for details on anonymous authentication (the important thing to understand is that if an anonymous user can access a page, it does not automatically mean that an authenticated user can access it too).

BWT, ROLE_ANONYMOUS is a built-in role, but ROLE_USER is not, as explained here. You need to make sure ROLE_USER is assigned to the user.

This answer explains why patterns should end with /**.

Community
  • 1
  • 1
Alexey
  • 2,542
  • 4
  • 31
  • 53
  • Just tried and working nicely! Thanks for this! I will just read the articles/links you suggested try couple of things and get back to you.Thanks, you saved me lot of time. – shippi Jan 02 '14 at 10:52
0

Try using this configuration which allows anonymous access to these urls:

<http>
        <intercept-url pattern="/**" access="ROLE_USER" />
        <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <intercept-url pattern="/view_register.htm" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <form-login login-page="/login" default-target-url="/game" authentication-failure-url="/failedlogin" />
        <logout logout-success-url="/login" />
</http>

When you specify the following:

<intercept-url pattern="/game*" access="ROLE_USER" />

Only URLs like ~/game* will be protected, leaving all other URLs unprotected.

Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
  • Thanks for the quick response! Just tried your solution (with a small modification - just moved the /** to the bottom of the intercept-url chain) but still the same issue. After hitting localhost:8080/webappName i am redirected to the login.jsp what is cool. Even i dont enter any username or pass just hit the submit the method handling the /login is called and i am just redirected to the same jsp without any error. Of course with good credentials the error is displayed: Your login attempt was not successful, try again. Caused : Interesting and quite frustrating. – shippi Jan 02 '14 at 00:24
  • "When you specify the following: Only URLs like ~/game* will be protected, leaving all other URLs unprotected." Yeah i know, but if i have just /game* the login.jsp behaves correctly. If the credentials are wrong displays the error message as it should and if i enter correct password and username I can hit the /game. But with /** it behaves exactly in the oposite way. Tried couple of syntax variations of the spring security config and still the same issue. But yeah thanks for you answer anyway. – shippi Jan 02 '14 at 00:39
  • @shippi, can you add * to the intercept-url pattern for login and see like – sasankad Jan 02 '14 at 00:48
  • @sasankad - still the same :( – shippi Jan 02 '14 at 00:52
  • @shippi, then try this – sasankad Jan 02 '14 at 00:55
  • End up in error: The use of "filters='none'" is no longer supported. Please define a separate element for the pattern you want to exclude and use the attribute "security='none'". I am using spring 3.2.0. – shippi Jan 02 '14 at 00:57