Skip to content

Commit c1b9035

Browse files
Kehrlannrwinch
authored andcommitted
Use static CSS in OneTimeToken default UI
1 parent e958ff2 commit c1b9035

File tree

4 files changed

+27
-267
lines changed

4 files changed

+27
-267
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.springframework.security.web.authentication.ott.OneTimeTokenAuthenticationConverter;
4747
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
4848
import org.springframework.security.web.authentication.ui.DefaultOneTimeTokenSubmitPageGeneratingFilter;
49+
import org.springframework.security.web.authentication.ui.DefaultResourcesFilter;
4950
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
5051
import org.springframework.security.web.context.SecurityContextRepository;
5152
import org.springframework.security.web.csrf.CsrfToken;
@@ -136,6 +137,7 @@ private void configureOttGenerateFilter(H http) {
136137
generateFilter.setGeneratedOneTimeTokenHandler(getGeneratedOneTimeTokenHandler(http));
137138
generateFilter.setRequestMatcher(antMatcher(HttpMethod.POST, this.generateTokenUrl));
138139
http.addFilter(postProcess(generateFilter));
140+
http.addFilter(DefaultResourcesFilter.css());
139141
}
140142

141143
private GeneratedOneTimeTokenHandler getGeneratedOneTimeTokenHandler(H http) {

config/src/test/java/org/springframework/security/config/annotation/web/configurers/ott/OneTimeTokenLoginConfigurerTests.java

Lines changed: 20 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import jakarta.servlet.ServletException;
2222
import jakarta.servlet.http.HttpServletRequest;
2323
import jakarta.servlet.http.HttpServletResponse;
24+
import org.hamcrest.Matchers;
2425
import org.junit.jupiter.api.Test;
2526
import org.junit.jupiter.api.extension.ExtendWith;
2627

@@ -53,6 +54,7 @@
5354
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
5455
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
5556
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
57+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
5658
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
5759
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
5860

@@ -64,143 +66,6 @@ public class OneTimeTokenLoginConfigurerTests {
6466
@Autowired(required = false)
6567
MockMvc mvc;
6668

67-
public static final String EXPECTED_HTML_HEAD = """
68-
<!DOCTYPE html>
69-
<html lang="en">
70-
<head>
71-
<meta charset="utf-8">
72-
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
73-
<meta name="description" content="">
74-
<meta name="author" content="">
75-
<title>Please sign in</title>
76-
<style>
77-
/* General layout */
78-
body {
79-
font-family: system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
80-
background-color: #eee;
81-
padding: 40px 0;
82-
margin: 0;
83-
line-height: 1.5;
84-
}
85-
\s\s\s\s
86-
h2 {
87-
margin-top: 0;
88-
margin-bottom: 0.5rem;
89-
font-size: 2rem;
90-
font-weight: 500;
91-
line-height: 2rem;
92-
}
93-
\s\s\s\s
94-
.content {
95-
margin-right: auto;
96-
margin-left: auto;
97-
padding-right: 15px;
98-
padding-left: 15px;
99-
width: 100%;
100-
box-sizing: border-box;
101-
}
102-
\s\s\s\s
103-
@media (min-width: 800px) {
104-
.content {
105-
max-width: 760px;
106-
}
107-
}
108-
\s\s\s\s
109-
/* Components */
110-
a,
111-
a:visited {
112-
text-decoration: none;
113-
color: #06f;
114-
}
115-
\s\s\s\s
116-
a:hover {
117-
text-decoration: underline;
118-
color: #003c97;
119-
}
120-
\s\s\s\s
121-
input[type="text"],
122-
input[type="password"] {
123-
height: auto;
124-
width: 100%;
125-
font-size: 1rem;
126-
padding: 0.5rem;
127-
box-sizing: border-box;
128-
}
129-
\s\s\s\s
130-
button {
131-
padding: 0.5rem 1rem;
132-
font-size: 1.25rem;
133-
line-height: 1.5;
134-
border: none;
135-
border-radius: 0.1rem;
136-
width: 100%;
137-
}
138-
\s\s\s\s
139-
button.primary {
140-
color: #fff;
141-
background-color: #06f;
142-
}
143-
\s\s\s\s
144-
.alert {
145-
padding: 0.75rem 1rem;
146-
margin-bottom: 1rem;
147-
line-height: 1.5;
148-
border-radius: 0.1rem;
149-
width: 100%;
150-
box-sizing: border-box;
151-
border-width: 1px;
152-
border-style: solid;
153-
}
154-
\s\s\s\s
155-
.alert.alert-danger {
156-
color: #6b1922;
157-
background-color: #f7d5d7;
158-
border-color: #eab6bb;
159-
}
160-
\s\s\s\s
161-
.alert.alert-success {
162-
color: #145222;
163-
background-color: #d1f0d9;
164-
border-color: #c2ebcb;
165-
}
166-
\s\s\s\s
167-
.screenreader {
168-
position: absolute;
169-
clip: rect(0 0 0 0);
170-
height: 1px;
171-
width: 1px;
172-
padding: 0;
173-
border: 0;
174-
overflow: hidden;
175-
}
176-
\s\s\s\s
177-
table {
178-
width: 100%;
179-
max-width: 100%;
180-
margin-bottom: 2rem;
181-
}
182-
\s\s\s\s
183-
.table-striped tr:nth-of-type(2n + 1) {
184-
background-color: #e1e1e1;
185-
}
186-
\s\s\s\s
187-
td {
188-
padding: 0.75rem;
189-
vertical-align: top;
190-
}
191-
\s\s\s\s
192-
/* Login / logout layouts */
193-
.login-form,
194-
.logout-form {
195-
max-width: 340px;
196-
padding: 0 15px 15px 15px;
197-
margin: 0 auto 2rem auto;
198-
box-sizing: border-box;
199-
}
200-
</style>
201-
</head>
202-
""";
203-
20469
@Test
20570
void oneTimeTokenWhenCorrectTokenThenCanAuthenticate() throws Exception {
20671
this.spring.register(OneTimeTokenDefaultConfig.class).autowire();
@@ -252,6 +117,14 @@ void oneTimeTokenWhenWrongTokenThenAuthenticationFail() throws Exception {
252117
.andExpectAll(status().isFound(), redirectedUrl("/login?error"), unauthenticated());
253118
}
254119

120+
@Test
121+
void oneTimeTokenWhenConfiguredThenServesCss() throws Exception {
122+
this.spring.register(OneTimeTokenDefaultConfig.class).autowire();
123+
this.mvc.perform(get("/default-ui.css"))
124+
.andExpect(status().isOk())
125+
.andExpect(content().string(Matchers.containsString("body {")));
126+
}
127+
255128
@Test
256129
void oneTimeTokenWhenFormLoginConfiguredThenRendersRequestTokenForm() throws Exception {
257130
this.spring.register(OneTimeTokenFormLoginConfig.class).autowire();
@@ -262,8 +135,17 @@ void oneTimeTokenWhenFormLoginConfiguredThenRendersRequestTokenForm() throws Exc
262135
.andExpect((result) -> {
263136
CsrfToken token = (CsrfToken) result.getRequest().getAttribute(CsrfToken.class.getName());
264137
assertThat(result.getResponse().getContentAsString()).isEqualTo(
265-
EXPECTED_HTML_HEAD +
266138
"""
139+
<!DOCTYPE html>
140+
<html lang="en">
141+
<head>
142+
<meta charset="utf-8">
143+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
144+
<meta name="description" content="">
145+
<meta name="author" content="">
146+
<title>Please sign in</title>
147+
<link href="/default-ui.css" rel="stylesheet" />
148+
</head>
267149
<body>
268150
<div class="content">
269151
<form class="login-form" method="post" action="/login">

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import jakarta.servlet.http.HttpServletRequest;
2929
import jakarta.servlet.http.HttpServletResponse;
3030

31-
import org.springframework.security.web.util.CssUtils;
3231
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
3332
import org.springframework.security.web.util.matcher.RequestMatcher;
3433
import org.springframework.util.Assert;
@@ -64,9 +63,10 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
6463
}
6564

6665
private String generateHtml(HttpServletRequest request) {
66+
String contextPath = request.getContextPath();
67+
6768
String token = request.getParameter("token");
6869
String tokenValue = StringUtils.hasText(token) ? token : "";
69-
String contextPath = request.getContextPath();
7070

7171
String hiddenInputs = this.resolveHiddenInputs.apply(request)
7272
.entrySet()
@@ -75,7 +75,7 @@ private String generateHtml(HttpServletRequest request) {
7575
.collect(Collectors.joining("\n"));
7676

7777
return HtmlTemplates.fromTemplate(ONE_TIME_TOKEN_SUBMIT_PAGE_TEMPLATE)
78-
.withRawHtml("cssStyle", CssUtils.getCssStyleBlock().indent(4))
78+
.withValue("contextPath", contextPath)
7979
.withValue("tokenValue", tokenValue)
8080
.withValue("loginProcessingUrl", contextPath + this.loginProcessingUrl)
8181
.withRawHtml("hiddenInputs", hiddenInputs)
@@ -116,7 +116,7 @@ public void setLoginProcessingUrl(String loginProcessingUrl) {
116116
<title>One-Time Token Login</title>
117117
<meta charset="utf-8"/>
118118
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
119-
{{cssStyle}}
119+
<link href="{{contextPath}}/default-ui.css" rel="stylesheet" />
120120
</head>
121121
<body>
122122
<div class="container">

web/src/test/java/org/springframework/security/web/authentication/ui/DefaultOneTimeTokenSubmitPageGeneratingFilterTests.java

Lines changed: 1 addition & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -110,131 +110,7 @@ void filterThenRenders() throws Exception {
110110
<title>One-Time Token Login</title>
111111
<meta charset="utf-8"/>
112112
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
113-
<style>
114-
/* General layout */
115-
body {
116-
font-family: system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
117-
background-color: #eee;
118-
padding: 40px 0;
119-
margin: 0;
120-
line-height: 1.5;
121-
}
122-
\s
123-
h2 {
124-
margin-top: 0;
125-
margin-bottom: 0.5rem;
126-
font-size: 2rem;
127-
font-weight: 500;
128-
line-height: 2rem;
129-
}
130-
\s
131-
.content {
132-
margin-right: auto;
133-
margin-left: auto;
134-
padding-right: 15px;
135-
padding-left: 15px;
136-
width: 100%;
137-
box-sizing: border-box;
138-
}
139-
\s
140-
@media (min-width: 800px) {
141-
.content {
142-
max-width: 760px;
143-
}
144-
}
145-
\s
146-
/* Components */
147-
a,
148-
a:visited {
149-
text-decoration: none;
150-
color: #06f;
151-
}
152-
\s
153-
a:hover {
154-
text-decoration: underline;
155-
color: #003c97;
156-
}
157-
\s
158-
input[type="text"],
159-
input[type="password"] {
160-
height: auto;
161-
width: 100%;
162-
font-size: 1rem;
163-
padding: 0.5rem;
164-
box-sizing: border-box;
165-
}
166-
\s
167-
button {
168-
padding: 0.5rem 1rem;
169-
font-size: 1.25rem;
170-
line-height: 1.5;
171-
border: none;
172-
border-radius: 0.1rem;
173-
width: 100%;
174-
}
175-
\s
176-
button.primary {
177-
color: #fff;
178-
background-color: #06f;
179-
}
180-
\s
181-
.alert {
182-
padding: 0.75rem 1rem;
183-
margin-bottom: 1rem;
184-
line-height: 1.5;
185-
border-radius: 0.1rem;
186-
width: 100%;
187-
box-sizing: border-box;
188-
border-width: 1px;
189-
border-style: solid;
190-
}
191-
\s
192-
.alert.alert-danger {
193-
color: #6b1922;
194-
background-color: #f7d5d7;
195-
border-color: #eab6bb;
196-
}
197-
\s
198-
.alert.alert-success {
199-
color: #145222;
200-
background-color: #d1f0d9;
201-
border-color: #c2ebcb;
202-
}
203-
\s
204-
.screenreader {
205-
position: absolute;
206-
clip: rect(0 0 0 0);
207-
height: 1px;
208-
width: 1px;
209-
padding: 0;
210-
border: 0;
211-
overflow: hidden;
212-
}
213-
\s
214-
table {
215-
width: 100%;
216-
max-width: 100%;
217-
margin-bottom: 2rem;
218-
}
219-
\s
220-
.table-striped tr:nth-of-type(2n + 1) {
221-
background-color: #e1e1e1;
222-
}
223-
\s
224-
td {
225-
padding: 0.75rem;
226-
vertical-align: top;
227-
}
228-
\s
229-
/* Login / logout layouts */
230-
.login-form,
231-
.logout-form {
232-
max-width: 340px;
233-
padding: 0 15px 15px 15px;
234-
margin: 0 auto 2rem auto;
235-
box-sizing: border-box;
236-
}
237-
</style>
113+
<link href="/default-ui.css" rel="stylesheet" />
238114
</head>
239115
<body>
240116
<div class="container">

0 commit comments

Comments
 (0)