Modernize Default Log In Page

Fixes: gh-5515
This commit is contained in:
Rob Winch 2018-07-09 12:52:52 -05:00
parent a66b945ab7
commit 05ed028f9d
13 changed files with 384 additions and 188 deletions

View File

@ -53,15 +53,33 @@ public class DefaultLoginPageConfigurerTests extends BaseSpringSpec {
request.requestURI = "/login"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</table>
</form></body></html>"""
response.getContentAsString() == """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Please sign in</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="http://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
</head>
<body>
<div class="container">
<form class="form-signin" method="post" action="/login">
<h2 class="form-signin-heading">Please sign in</h2>
<p>
<label for="username" class="sr-only">Username</label>
<input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus>
</p>
<p>
<label for="password" class="sr-only">Password</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
</p>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</body></html>"""
when: "fail to log in"
super.setup()
request.servletPath = "/login"
@ -77,15 +95,33 @@ public class DefaultLoginPageConfigurerTests extends BaseSpringSpec {
request.queryString = "error"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<p style='color:red;'>Your login attempt was not successful, try again.<br/><br/>Reason: Bad credentials</p><h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</table>
</form></body></html>"""
response.getContentAsString() == """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Please sign in</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="http://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
</head>
<body>
<div class="container">
<form class="form-signin" method="post" action="/login">
<h2 class="form-signin-heading">Please sign in</h2>
<div class="alert alert-danger" role="alert">Bad credentials</div> <p>
<label for="username" class="sr-only">Username</label>
<input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus>
</p>
<p>
<label for="password" class="sr-only">Password</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
</p>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</body></html>"""
when: "login success"
super.setup()
request.servletPath = "/login"
@ -106,15 +142,33 @@ public class DefaultLoginPageConfigurerTests extends BaseSpringSpec {
request.method = "GET"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default success page"
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<p style='color:green;'>You have been logged out</p><h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</table>
</form></body></html>"""
response.getContentAsString() == """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Please sign in</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="http://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
</head>
<body>
<div class="container">
<form class="form-signin" method="post" action="/login">
<h2 class="form-signin-heading">Please sign in</h2>
<div class="alert alert-success" role="alert">You have been signed out</div> <p>
<label for="username" class="sr-only">Username</label>
<input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus>
</p>
<p>
<label for="password" class="sr-only">Password</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
</p>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</body></html>"""
}
@Configuration
@ -191,16 +245,34 @@ public class DefaultLoginPageConfigurerTests extends BaseSpringSpec {
request.requestURI = "/login"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td><input type='checkbox' name='remember-me'/></td><td>Remember me on this computer.</td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</table>
</form></body></html>"""
response.getContentAsString() == """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Please sign in</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="http://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
</head>
<body>
<div class="container">
<form class="form-signin" method="post" action="/login">
<h2 class="form-signin-heading">Please sign in</h2>
<p>
<label for="username" class="sr-only">Username</label>
<input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus>
</p>
<p>
<label for="password" class="sr-only">Password</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
</p>
<p><input type='checkbox' name='remember-me'/> Remember me on this computer.</p>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</body></html>"""
}
@Configuration
@ -224,13 +296,29 @@ public class DefaultLoginPageConfigurerTests extends BaseSpringSpec {
request.requestURI = "/login"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><h3>Login with OpenID Identity</h3><form name='oidf' action='/login/openid' method='POST'>
<table>
<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
</table>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</form></body></html>"""
response.getContentAsString() == """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Please sign in</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="http://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
</head>
<body>
<div class="container">
<form name="oidf" class="form-signin" method="post" action="/login/openid">
<h2 class="form-signin-heading">Login with OpenID Identity</h2>
<p>
<label for="username" class="sr-only">Identity</label>
<input type="text" id="username" name="openid_identifier" class="form-control" placeholder="Username" required autofocus>
</p>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</body></html>"""
}
@Configuration
@ -252,23 +340,44 @@ public class DefaultLoginPageConfigurerTests extends BaseSpringSpec {
request.requestURI = "/login"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td><input type='checkbox' name='remember-me'/></td><td>Remember me on this computer.</td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</table>
</form><h3>Login with OpenID Identity</h3><form name='oidf' action='/login/openid' method='POST'>
<table>
<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
<tr><td><input type='checkbox' name='remember-me'></td><td>Remember me on this computer.</td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
</table>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</form></body></html>"""
response.getContentAsString() == """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Please sign in</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="http://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
</head>
<body>
<div class="container">
<form class="form-signin" method="post" action="/login">
<h2 class="form-signin-heading">Please sign in</h2>
<p>
<label for="username" class="sr-only">Username</label>
<input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus>
</p>
<p>
<label for="password" class="sr-only">Password</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
</p>
<p><input type='checkbox' name='remember-me'/> Remember me on this computer.</p>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
<form name="oidf" class="form-signin" method="post" action="/login/openid">
<h2 class="form-signin-heading">Login with OpenID Identity</h2>
<p>
<label for="username" class="sr-only">Identity</label>
<input type="text" id="username" name="openid_identifier" class="form-control" placeholder="Username" required autofocus>
</p>
<p><input type='checkbox' name='remember-me'/> Remember me on this computer.</p>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</body></html>"""
}
@Configuration

View File

@ -54,14 +54,32 @@ public class FormLoginBeanDefinitionParserTests {
this.spring.configLocations(this.xml("Simple")).autowire();
String expectedContent =
"<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>\n" +
"<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>\n" +
"<table>\n" +
" <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>\n" +
" <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>\n" +
" <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n" +
"</table>\n" +
"</form></body></html>";
"<!DOCTYPE html>\n"
+ "<html lang=\"en\">\n"
+ " <head>\n"
+ " <meta charset=\"utf-8\">\n"
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
+ " <meta name=\"description\" content=\"\">\n"
+ " <meta name=\"author\" content=\"\">\n"
+ " <title>Please sign in</title>\n"
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
+ " <link href=\"http://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
+ " </head>\n"
+ " <body>\n"
+ " <div class=\"container\">\n"
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
+ " <p>\n"
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
+ " </p>\n"
+ " <p>\n"
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
+ " </p>\n"
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
+ " </form>\n"
+ "</body></html>";
this.mvc.perform(get("/login")).andExpect(content().string(expectedContent));
}
@ -73,14 +91,31 @@ public class FormLoginBeanDefinitionParserTests {
this.spring.configLocations(this.xml("WithCustomAttributes")).autowire();
String expectedContent =
"<html><head><title>Login Page</title></head><body onload='document.f.custom_user.focus();'>\n" +
"<h3>Login with Username and Password</h3><form name='f' action='/signin' method='POST'>\n" +
"<table>\n" +
" <tr><td>User:</td><td><input type='text' name='custom_user' value=''></td></tr>\n" +
" <tr><td>Password:</td><td><input type='password' name='custom_pass'/></td></tr>\n" +
" <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n" +
"</table>\n" +
"</form></body></html>";
"<!DOCTYPE html>\n"
+ "<html lang=\"en\">\n" + " <head>\n"
+ " <meta charset=\"utf-8\">\n"
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
+ " <meta name=\"description\" content=\"\">\n"
+ " <meta name=\"author\" content=\"\">\n"
+ " <title>Please sign in</title>\n"
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
+ " <link href=\"http://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
+ " </head>\n"
+ " <body>\n"
+ " <div class=\"container\">\n"
+ " <form class=\"form-signin\" method=\"post\" action=\"/signin\">\n"
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
+ " <p>\n"
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
+ " <input type=\"text\" id=\"username\" name=\"custom_user\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
+ " </p>\n"
+ " <p>\n"
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
+ " <input type=\"password\" id=\"password\" name=\"custom_pass\" class=\"form-control\" placeholder=\"Password\" required>\n"
+ " </p>\n"
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
+ " </form>\n"
+ "</body></html>";
this.mvc.perform(get("/login")).andExpect(content().string(expectedContent));
}
@ -92,19 +127,38 @@ public class FormLoginBeanDefinitionParserTests {
this.spring.configLocations(this.xml("WithOpenId")).autowire();
String expectedContent =
"<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>\n" +
"<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>\n" +
"<table>\n" +
" <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>\n" +
" <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>\n" +
" <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n" +
"</table>\n" +
"</form><h3>Login with OpenID Identity</h3><form name='oidf' action='/login/openid' method='POST'>\n" +
"<table>\n" +
" <tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>\n" +
" <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n" +
"</table>\n" +
"</form></body></html>";
"<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + " <head>\n"
+ " <meta charset=\"utf-8\">\n"
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
+ " <meta name=\"description\" content=\"\">\n"
+ " <meta name=\"author\" content=\"\">\n"
+ " <title>Please sign in</title>\n"
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
+ " <link href=\"http://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
+ " </head>\n"
+ " <body>\n"
+ " <div class=\"container\">\n"
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
+ " <p>\n"
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
+ " </p>\n"
+ " <p>\n"
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
+ " </p>\n"
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
+ " </form>\n"
+ " <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"/login/openid\">\n"
+ " <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n"
+ " <p>\n"
+ " <label for=\"username\" class=\"sr-only\">Identity</label>\n"
+ " <input type=\"text\" id=\"username\" name=\"openid_identifier\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
+ " </p>\n"
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
+ " </form>\n"
+ "</body></html>";
this.mvc.perform(get("/login")).andExpect(content().string(expectedContent));
}
@ -116,19 +170,38 @@ public class FormLoginBeanDefinitionParserTests {
this.spring.configLocations(this.xml("WithOpenIdCustomAttributes")).autowire();
String expectedContent =
"<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>\n" +
"<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>\n" +
"<table>\n" +
" <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>\n" +
" <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>\n" +
" <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n" +
"</table>\n" +
"</form><h3>Login with OpenID Identity</h3><form name='oidf' action='/signin' method='POST'>\n" +
"<table>\n" +
" <tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>\n" +
" <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n" +
"</table>\n" +
"</form></body></html>";
"<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + " <head>\n"
+ " <meta charset=\"utf-8\">\n"
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
+ " <meta name=\"description\" content=\"\">\n"
+ " <meta name=\"author\" content=\"\">\n"
+ " <title>Please sign in</title>\n"
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
+ " <link href=\"http://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
+ " </head>\n"
+ " <body>\n"
+ " <div class=\"container\">\n"
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
+ " <p>\n"
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
+ " </p>\n"
+ " <p>\n"
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
+ " </p>\n"
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
+ " </form>\n"
+ " <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"/signin\">\n"
+ " <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n"
+ " <p>\n"
+ " <label for=\"username\" class=\"sr-only\">Identity</label>\n"
+ " <input type=\"text\" id=\"username\" name=\"openid_identifier\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
+ " </p>\n"
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
+ " </form>\n"
+ "</body></html>";
this.mvc.perform(get("/login")).andExpect(content().string(expectedContent));
}

View File

@ -218,7 +218,7 @@ public class OAuth2LoginApplicationTests {
page = this.webClient.getPage(new URL(authorizationResponseUri));
assertThat(page.getBaseURL()).isEqualTo(loginErrorPageUrl);
HtmlElement errorElement = page.getBody().getFirstByXPath("p");
HtmlElement errorElement = page.getBody().getFirstByXPath("div");
assertThat(errorElement).isNotNull();
assertThat(errorElement.asText()).contains("authorization_request_not_found");
}
@ -248,7 +248,7 @@ public class OAuth2LoginApplicationTests {
page = this.webClient.getPage(new URL(authorizationResponseUri));
assertThat(page.getBaseURL()).isEqualTo(loginErrorPageUrl);
HtmlElement errorElement = page.getBody().getFirstByXPath("p");
HtmlElement errorElement = page.getBody().getFirstByXPath("div");
assertThat(errorElement).isNotNull();
assertThat(errorElement.asText()).contains("authorization_request_not_found");
}
@ -284,13 +284,13 @@ public class OAuth2LoginApplicationTests {
page = this.webClient.getPage(new URL(authorizationResponseUri));
assertThat(page.getBaseURL()).isEqualTo(loginErrorPageUrl);
HtmlElement errorElement = page.getBody().getFirstByXPath("p");
HtmlElement errorElement = page.getBody().getFirstByXPath("div");
assertThat(errorElement).isNotNull();
assertThat(errorElement.asText()).contains("invalid_redirect_uri_parameter");
}
private void assertLoginPage(HtmlPage page) throws Exception {
assertThat(page.getTitleText()).isEqualTo("Login Page");
assertThat(page.getTitleText()).isEqualTo("Please sign in");
int expectedClients = 4;

View File

@ -37,7 +37,7 @@ public class LoginPage {
}
public LoginPage assertAt() {
assertThat(this.webDriver.getTitle()).isEqualTo("Login Page");
assertThat(this.webDriver.getTitle()).isEqualTo("Please sign in");
return this;
}
@ -49,7 +49,7 @@ public class LoginPage {
private WebDriver webDriver;
private WebElement username;
private WebElement password;
@FindBy(css = "input[type=submit]")
@FindBy(css = "button[type=submit]")
private WebElement submit;
public LoginForm(WebDriver webDriver) {

View File

@ -37,7 +37,7 @@ public class LoginPage {
}
public LoginPage assertAt() {
assertThat(this.webDriver.getTitle()).isEqualTo("Login Page");
assertThat(this.webDriver.getTitle()).isEqualTo("Please sign in");
return this;
}
@ -49,7 +49,7 @@ public class LoginPage {
private WebDriver webDriver;
private WebElement username;
private WebElement password;
@FindBy(css = "input[type=submit]")
@FindBy(css = "button[type=submit]")
private WebElement submit;
public LoginForm(WebDriver webDriver) {

View File

@ -37,7 +37,7 @@ public class LoginPage {
}
public LoginPage assertAt() {
assertThat(this.webDriver.getTitle()).isEqualTo("Login Page");
assertThat(this.webDriver.getTitle()).isEqualTo("Please sign in");
return this;
}
@ -49,7 +49,7 @@ public class LoginPage {
private WebDriver webDriver;
private WebElement username;
private WebElement password;
@FindBy(css = "input[type=submit]")
@FindBy(css = "button[type=submit]")
private WebElement submit;
public LoginForm(WebDriver webDriver) {

View File

@ -37,7 +37,7 @@ public class LoginPage {
}
public LoginPage assertAt() {
assertThat(this.webDriver.getTitle()).isEqualTo("Login Page");
assertThat(this.webDriver.getTitle()).isEqualTo("Please sign in");
return this;
}
@ -49,7 +49,7 @@ public class LoginPage {
private WebDriver webDriver;
private WebElement username;
private WebElement password;
@FindBy(css = "input[type=submit]")
@FindBy(css = "button[type=submit]")
private WebElement submit;
public LoginForm(WebDriver webDriver) {

View File

@ -39,7 +39,7 @@ public class LoginPage {
}
public LoginPage assertAt() {
assertThat(this.webDriver.getTitle()).isEqualTo("Login Page");
assertThat(this.webDriver.getTitle()).isEqualTo("Please sign in");
return this;
}
@ -51,7 +51,7 @@ public class LoginPage {
private WebDriver webDriver;
private WebElement username;
private WebElement password;
@FindBy(css = "input[type=submit]")
@FindBy(css = "button[type=submit]")
private WebElement submit;
public LoginForm(WebDriver webDriver) {

View File

@ -27,8 +27,8 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Michael Simons
*/
public class LogoutPage extends LoginPage {
@FindBy(css = "p")
private WebElement p;
@FindBy(css = "div[role=alert]")
private WebElement alert;
public LogoutPage(WebDriver webDriver) {
super(webDriver);
@ -38,7 +38,7 @@ public class LogoutPage extends LoginPage {
public LogoutPage assertAt() {
super.assertAt();
assertThat(p.getText()).isEqualTo("You have been logged out");
assertThat(this.alert.getText()).isEqualTo("You have been signed out");
return this;
}
}

View File

@ -39,7 +39,7 @@ public class LoginPage {
}
public LoginPage assertAt() {
assertThat(this.webDriver.getTitle()).isEqualTo("Login Page");
assertThat(this.webDriver.getTitle()).isEqualTo("Please sign in");
return this;
}
@ -51,7 +51,7 @@ public class LoginPage {
private WebDriver webDriver;
private WebElement username;
private WebElement password;
@FindBy(css = "input[type=submit]")
@FindBy(css = "button[type=submit]")
private WebElement submit;
public LoginForm(WebDriver webDriver) {

View File

@ -27,8 +27,8 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Michael Simons
*/
public class LogoutPage extends LoginPage {
@FindBy(css = "p")
private WebElement p;
@FindBy(css = "div[role=alert]")
private WebElement alert;
public LogoutPage(WebDriver webDriver) {
super(webDriver);
@ -38,7 +38,7 @@ public class LogoutPage extends LoginPage {
public LogoutPage assertAt() {
super.assertAt();
assertThat(p.getText()).isEqualTo("You have been logged out");
assertThat(this.alert.getText()).isEqualTo("You have been signed out");
return this;
}
}

View File

@ -208,7 +208,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
private String generateLoginPageHtml(HttpServletRequest request, boolean loginError,
boolean logoutSuccess) {
String errorMsg = "none";
String errorMsg = "Invalid credentials";
if (loginError) {
HttpSession session = request.getSession(false);
@ -216,82 +216,76 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
if (session != null) {
AuthenticationException ex = (AuthenticationException) session
.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
errorMsg = ex != null ? ex.getMessage() : "none";
errorMsg = ex != null ? ex.getMessage() : "Invalid credentials";
}
}
StringBuilder sb = new StringBuilder();
sb.append("<html><head><title>Login Page</title></head>");
sb.append("<!DOCTYPE html>\n"
+ "<html lang=\"en\">\n"
+ " <head>\n"
+ " <meta charset=\"utf-8\">\n"
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
+ " <meta name=\"description\" content=\"\">\n"
+ " <meta name=\"author\" content=\"\">\n"
+ " <title>Please sign in</title>\n"
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
+ " <link href=\"http://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
+ " </head>\n"
+ " <body>\n"
+ " <div class=\"container\">\n");
if (formLoginEnabled) {
sb.append("<body onload='document.f.").append(usernameParameter)
.append(".focus();'>\n");
}
if (loginError) {
sb.append("<p style='color:red;'>Your login attempt was not successful, try again.<br/><br/>Reason: ");
sb.append(errorMsg);
sb.append("</p>");
}
if (logoutSuccess) {
sb.append("<p style='color:green;'>You have been logged out</p>");
}
if (formLoginEnabled) {
sb.append("<h3>Login with Username and Password</h3>");
sb.append("<form name='f' action='").append(request.getContextPath())
.append(authenticationUrl).append("' method='POST'>\n");
sb.append("<table>\n");
sb.append(" <tr><td>User:</td><td><input type='text' name='");
sb.append(usernameParameter).append("' value='").append("'></td></tr>\n");
sb.append(" <tr><td>Password:</td><td><input type='password' name='")
.append(passwordParameter).append("'/></td></tr>\n");
if (rememberMeParameter != null) {
sb.append(" <tr><td><input type='checkbox' name='")
.append(rememberMeParameter)
.append("'/></td><td>Remember me on this computer.</td></tr>\n");
}
sb.append(" <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n");
renderHiddenInputs(sb, request);
sb.append("</table>\n");
sb.append("</form>");
String contextPath = request.getContextPath();
if (this.formLoginEnabled) {
sb.append(" <form class=\"form-signin\" method=\"post\" action=\"" + contextPath + this.authenticationUrl + "\">\n"
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
+ createError(loginError, errorMsg)
+ createLogoutSuccess(logoutSuccess)
+ " <p>\n"
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
+ " <input type=\"text\" id=\"username\" name=\"" + this.usernameParameter + "\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
+ " </p>\n"
+ " <p>\n"
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
+ " <input type=\"password\" id=\"password\" name=\"" + this.passwordParameter + "\" class=\"form-control\" placeholder=\"Password\" required>\n"
+ " </p>\n"
+ createRememberMe(this.rememberMeParameter)
+ renderHiddenInputs(request)
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
+ " </form>\n");
}
if (openIdEnabled) {
sb.append("<h3>Login with OpenID Identity</h3>");
sb.append("<form name='oidf' action='").append(request.getContextPath())
.append(openIDauthenticationUrl).append("' method='POST'>\n");
sb.append("<table>\n");
sb.append(" <tr><td>Identity:</td><td><input type='text' size='30' name='");
sb.append(openIDusernameParameter).append("'/></td></tr>\n");
if (openIDrememberMeParameter != null) {
sb.append(" <tr><td><input type='checkbox' name='")
.append(openIDrememberMeParameter)
.append("'></td><td>Remember me on this computer.</td></tr>\n");
}
sb.append(" <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n");
sb.append("</table>\n");
renderHiddenInputs(sb, request);
sb.append("</form>");
sb.append(" <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"" + contextPath + this.openIDauthenticationUrl + "\">\n"
+ " <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n"
+ createError(loginError, errorMsg)
+ createLogoutSuccess(logoutSuccess)
+ " <p>\n"
+ " <label for=\"username\" class=\"sr-only\">Identity</label>\n"
+ " <input type=\"text\" id=\"username\" name=\"" + this.openIDusernameParameter + "\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
+ " </p>\n"
+ createRememberMe(this.openIDrememberMeParameter)
+ renderHiddenInputs(request)
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
+ " </form>\n");
}
if (oauth2LoginEnabled) {
sb.append("<h3>Login with OAuth 2.0</h3>");
sb.append("<table>\n");
sb.append("<h2 class=\"form-signin-heading\">Login with OAuth 2.0</h3>");
sb.append(createError(loginError, errorMsg));
sb.append(createLogoutSuccess(logoutSuccess));
sb.append("<table class=\"table table-striped\">\n");
for (Map.Entry<String, String> clientAuthenticationUrlToClientName : oauth2AuthenticationUrlToClientName.entrySet()) {
sb.append(" <tr><td>");
sb.append("<a href=\"").append(request.getContextPath()).append(clientAuthenticationUrlToClientName.getKey()).append("\">");
sb.append(HtmlUtils.htmlEscape(clientAuthenticationUrlToClientName.getValue(), "UTF-8"));
String url = clientAuthenticationUrlToClientName.getKey();
sb.append("<a href=\"").append(contextPath).append(url).append("\">");
String clientName = HtmlUtils.htmlEscape(clientAuthenticationUrlToClientName.getValue());
sb.append(clientName);
sb.append("</a>");
sb.append("</td></tr>\n");
}
sb.append("</table>\n");
sb.append("</table></div>\n");
}
sb.append("</body></html>");
@ -299,10 +293,21 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
return sb.toString();
}
private void renderHiddenInputs(StringBuilder sb, HttpServletRequest request) {
private String renderHiddenInputs(HttpServletRequest request) {
StringBuilder sb = new StringBuilder();
for(Map.Entry<String, String> input : this.resolveHiddenInputs.apply(request).entrySet()) {
sb.append(" <input name=\"").append(input.getKey()).append("\" type=\"hidden\" value=\"").append(input.getValue()).append("\" />\n");
sb.append("<input name=\"").append(input.getKey()).append("\" type=\"hidden\" value=\"").append(input.getValue()).append("\" />\n");
}
return sb.toString();
}
private String createRememberMe(String paramName) {
if (paramName == null) {
return "";
}
return "<p><input type='checkbox' name='"
+ paramName
+ "'/> Remember me on this computer.</p>\n";
}
private boolean isLogoutSuccess(HttpServletRequest request) {
@ -317,6 +322,14 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
return matches(request, failureUrl);
}
private static String createError(boolean isError, String message) {
return isError ? "<div class=\"alert alert-danger\" role=\"alert\">" + HtmlUtils.htmlEscape(message) + "</div>" : "";
}
private static String createLogoutSuccess(boolean isLogoutSuccess) {
return isLogoutSuccess ? "<div class=\"alert alert-success\" role=\"alert\">You have been signed out</div>" : "";
}
private boolean matches(HttpServletRequest request, String url) {
if (!"GET".equals(request.getMethod()) || url == null) {
return false;

View File

@ -122,7 +122,8 @@ public class LoginPageGeneratingWebFilter implements WebFilter {
boolean isLogoutSuccess = queryParams.containsKey("logout");
return " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
+ createError(isError) + createLogoutSuccess(isLogoutSuccess)
+ createError(isError)
+ createLogoutSuccess(isLogoutSuccess)
+ " <p>\n"
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"