Skip to content

Commit c123bb6

Browse files
committed
Make username Read-Only When Present
1 parent 5986d38 commit c123bb6

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public final class DefaultLoginPageConfigurer<H extends HttpSecurityBuilder<H>>
6868

6969
@Override
7070
public void init(H http) {
71+
this.loginPageGeneratingFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
7172
this.loginPageGeneratingFilter.setResolveHiddenInputs(DefaultLoginPageConfigurer.this::hiddenInputs);
7273
this.logoutPageGeneratingFilter.setResolveHiddenInputs(DefaultLoginPageConfigurer.this::hiddenInputs);
7374
http.setSharedObject(DefaultLoginPageGeneratingFilter.class, this.loginPageGeneratingFilter);

web/src/main/java/org/springframework/security/web/authentication/ui/DefaultLoginPageGeneratingFilter.java

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
5959

6060
public static final String ERROR_PARAMETER_NAME = "error";
6161

62+
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
63+
.getContextHolderStrategy();
64+
6265
private @Nullable String loginPageUrl;
6366

6467
private @Nullable String logoutSuccessUrl;
@@ -118,6 +121,10 @@ private void initAuthFilter(UsernamePasswordAuthenticationFilter authFilter) {
118121
}
119122
}
120123

124+
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
125+
this.securityContextHolderStrategy = securityContextHolderStrategy;
126+
}
127+
121128
/**
122129
* Sets a Function used to resolve a Map of the hidden inputs where the key is the
123130
* name of the input and the value is the value of the input. Typically this is used
@@ -307,6 +314,13 @@ private String renderFormLogin(HttpServletRequest request, boolean loginError, b
307314
return "";
308315
}
309316

317+
String username = getUsername();
318+
String usernameInput = (username == null) ? FORM_USERNAME_INPUT
319+
: HtmlTemplates.fromTemplate(FORM_READONLY_USERNAME_INPUT)
320+
.withValue("usernameParameter", this.usernameParameter)
321+
.withValue("username", username)
322+
.render();
323+
310324
String hiddenInputs = this.resolveHiddenInputs.apply(request)
311325
.entrySet()
312326
.stream()
@@ -317,7 +331,7 @@ private String renderFormLogin(HttpServletRequest request, boolean loginError, b
317331
.withValue("loginUrl", contextPath + this.authenticationUrl)
318332
.withRawHtml("errorMessage", renderError(loginError, errorMsg))
319333
.withRawHtml("logoutMessage", renderSuccess(logoutSuccess))
320-
.withValue("usernameParameter", this.usernameParameter)
334+
.withRawHtml("usernameInput", usernameInput)
321335
.withValue("passwordParameter", this.passwordParameter)
322336
.withRawHtml("rememberMeInput", renderRememberMe(this.rememberMeParameter))
323337
.withRawHtml("hiddenInputs", hiddenInputs)
@@ -337,11 +351,16 @@ private String renderOneTimeTokenLogin(HttpServletRequest request, boolean login
337351
.map((inputKeyValue) -> renderHiddenInput(inputKeyValue.getKey(), inputKeyValue.getValue()))
338352
.collect(Collectors.joining("\n"));
339353

354+
String username = getUsername();
355+
String usernameInput = (username == null) ? ONE_TIME_USERNAME_INPUT
356+
: HtmlTemplates.fromTemplate(ONE_TIME_READONLY_USERNAME_INPUT).withValue("username", username).render();
357+
340358
return HtmlTemplates.fromTemplate(ONE_TIME_TEMPLATE)
341359
.withValue("generateOneTimeTokenUrl", contextPath + this.generateOneTimeTokenUrl)
342360
.withRawHtml("errorMessage", renderError(loginError, errorMsg))
343361
.withRawHtml("logoutMessage", renderSuccess(logoutSuccess))
344362
.withRawHtml("hiddenInputs", hiddenInputs)
363+
.withRawHtml("usernameInput", usernameInput)
345364
.render();
346365
}
347366

@@ -410,6 +429,14 @@ private String renderRememberMe(@Nullable String paramName) {
410429
.render();
411430
}
412431

432+
private @Nullable String getUsername() {
433+
Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication();
434+
if (authentication != null && authentication.isAuthenticated()) {
435+
return authentication.getName();
436+
}
437+
return null;
438+
}
439+
413440
private boolean isLogoutSuccess(HttpServletRequest request) {
414441
return this.logoutSuccessUrl != null && matches(request, this.logoutSuccessUrl);
415442
}
@@ -511,7 +538,7 @@ private boolean matches(HttpServletRequest request, @Nullable String url) {
511538
{{errorMessage}}{{logoutMessage}}
512539
<p>
513540
<label for="username" class="screenreader">Username</label>
514-
<input type="text" id="username" name="{{usernameParameter}}" placeholder="Username" required autofocus>
541+
{{usernameInput}}
515542
</p>
516543
<p>
517544
<label for="password" class="screenreader">Password</label>
@@ -522,6 +549,14 @@ private boolean matches(HttpServletRequest request, @Nullable String url) {
522549
<button type="submit" class="primary">Sign in</button>
523550
</form>""";
524551

552+
private static final String FORM_READONLY_USERNAME_INPUT = """
553+
<input type="text" id="ott-username" name="{{usernameParameter}}" value="{{username}}" placeholder="Username" required readonly>
554+
""";
555+
556+
private static final String FORM_USERNAME_INPUT = """
557+
<input type="text" id="ott-username" name="{{usernameParameter}}" placeholder="Username" required>
558+
""";
559+
525560
private static final String HIDDEN_HTML_INPUT_TEMPLATE = """
526561
<input name="{{name}}" type="hidden" value="{{value}}" />
527562
""";
@@ -554,11 +589,19 @@ private boolean matches(HttpServletRequest request, @Nullable String url) {
554589
{{errorMessage}}{{logoutMessage}}
555590
<p>
556591
<label for="ott-username" class="screenreader">Username</label>
557-
<input type="text" id="ott-username" name="username" placeholder="Username" required>
592+
{{usernameInput}}
558593
</p>
559594
{{hiddenInputs}}
560595
<button class="primary" type="submit" form="ott-form">Send Token</button>
561596
</form>
562597
""";
563598

599+
private static final String ONE_TIME_READONLY_USERNAME_INPUT = """
600+
<input type="text" id="ott-username" name="username" value="{{username}}" placeholder="Username" required readonly>
601+
""";
602+
603+
private static final String ONE_TIME_USERNAME_INPUT = """
604+
<input type="text" id="ott-username" name="username" placeholder="Username" required>
605+
""";
606+
564607
}

0 commit comments

Comments
 (0)