Skip to content

Commit 2dbedf7

Browse files
peterkellereleftherias
authored andcommitted
Set charset of BasicAuthenticationFilter converter
Allow BasicAuthenticationFilter to pick up the given credentials charset. Fixes: gh-7835
1 parent 630eb10 commit 2dbedf7

File tree

2 files changed

+107
-1
lines changed

2 files changed

+107
-1
lines changed

web/src/main/java/org/springframework/security/web/authentication/www/BasicAuthenticationFilter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.security.web.authentication.www;
1818

1919
import java.io.IOException;
20+
import java.nio.charset.Charset;
2021

2122
import javax.servlet.FilterChain;
2223
import javax.servlet.ServletException;
@@ -276,6 +277,7 @@ public void setRememberMeServices(RememberMeServices rememberMeServices) {
276277
public void setCredentialsCharset(String credentialsCharset) {
277278
Assert.hasText(credentialsCharset, "credentialsCharset cannot be null or empty");
278279
this.credentialsCharset = credentialsCharset;
280+
this.authenticationConverter.setCredentialsCharset(Charset.forName(credentialsCharset));
279281
}
280282

281283
protected String getCredentialsCharset(HttpServletRequest httpRequest) {

web/src/test/java/org/springframework/security/web/authentication/www/BasicAuthenticationFilterTests.java

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616

1717
package org.springframework.security.web.authentication.www;
1818

19-
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.assertj.core.api.Assertions.*;
2020
import static org.mockito.AdditionalMatchers.not;
2121
import static org.mockito.Mockito.*;
2222

2323
import javax.servlet.FilterChain;
2424
import javax.servlet.ServletRequest;
2525
import javax.servlet.ServletResponse;
26+
import javax.servlet.http.HttpServletResponse;
2627

2728
import org.apache.commons.codec.binary.Base64;
2829
import org.junit.After;
@@ -40,6 +41,8 @@
4041
import org.springframework.security.web.authentication.WebAuthenticationDetails;
4142
import org.springframework.web.util.WebUtils;
4243

44+
import java.nio.charset.StandardCharsets;
45+
4346
/**
4447
* Tests {@link BasicAuthenticationFilter}.
4548
*
@@ -320,4 +323,105 @@ public void skippedOnErrorDispatch() throws Exception {
320323

321324
assertThat(response.getStatus()).isEqualTo(200);
322325
}
326+
327+
@Test
328+
public void doFilterWhenTokenAndFilterCharsetMatchDefaultThenAuthenticated() throws Exception {
329+
SecurityContextHolder.clearContext();
330+
331+
UsernamePasswordAuthenticationToken rodRequest = new UsernamePasswordAuthenticationToken("rod", "äöü");
332+
rodRequest.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest()));
333+
Authentication rod = new UsernamePasswordAuthenticationToken("rod", "äöü", AuthorityUtils.createAuthorityList("ROLE_1"));
334+
335+
manager = mock(AuthenticationManager.class);
336+
when(manager.authenticate(rodRequest)).thenReturn(rod);
337+
when(manager.authenticate(not(eq(rodRequest)))).thenThrow(new BadCredentialsException(""));
338+
339+
filter = new BasicAuthenticationFilter(manager, new BasicAuthenticationEntryPoint());
340+
341+
String token = "rod:äöü";
342+
MockHttpServletRequest request = new MockHttpServletRequest();
343+
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes(StandardCharsets.UTF_8))));
344+
request.setServletPath("/some_file.html");
345+
346+
MockHttpServletResponse response = new MockHttpServletResponse();
347+
348+
// Test
349+
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
350+
FilterChain chain = mock(FilterChain.class);
351+
352+
filter.doFilter(request, response, chain);
353+
354+
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
355+
verify(chain).doFilter(any(ServletRequest.class), any(ServletResponse.class));
356+
assertThat(SecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("rod");
357+
assertThat(SecurityContextHolder.getContext().getAuthentication().getCredentials()).isEqualTo("äöü");
358+
}
359+
360+
@Test
361+
public void doFilterWhenTokenAndFilterCharsetMatchNonDefaultThenAuthenticated() throws Exception {
362+
SecurityContextHolder.clearContext();
363+
364+
UsernamePasswordAuthenticationToken rodRequest = new UsernamePasswordAuthenticationToken("rod", "äöü");
365+
rodRequest.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest()));
366+
Authentication rod = new UsernamePasswordAuthenticationToken("rod", "äöü", AuthorityUtils.createAuthorityList("ROLE_1"));
367+
368+
manager = mock(AuthenticationManager.class);
369+
when(manager.authenticate(rodRequest)).thenReturn(rod);
370+
when(manager.authenticate(not(eq(rodRequest)))).thenThrow(new BadCredentialsException(""));
371+
372+
filter = new BasicAuthenticationFilter(manager, new BasicAuthenticationEntryPoint());
373+
filter.setCredentialsCharset("ISO-8859-1");
374+
375+
String token = "rod:äöü";
376+
MockHttpServletRequest request = new MockHttpServletRequest();
377+
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes(StandardCharsets.ISO_8859_1))));
378+
request.setServletPath("/some_file.html");
379+
380+
MockHttpServletResponse response = new MockHttpServletResponse();
381+
382+
// Test
383+
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
384+
FilterChain chain = mock(FilterChain.class);
385+
386+
filter.doFilter(request, response, chain);
387+
388+
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
389+
verify(chain).doFilter(any(ServletRequest.class), any(ServletResponse.class));
390+
assertThat(SecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("rod");
391+
assertThat(SecurityContextHolder.getContext().getAuthentication().getCredentials()).isEqualTo("äöü");
392+
}
393+
394+
@Test
395+
public void doFilterWhenTokenAndFilterCharsetDoNotMatchThenUnauthorized() throws Exception {
396+
SecurityContextHolder.clearContext();
397+
398+
UsernamePasswordAuthenticationToken rodRequest = new UsernamePasswordAuthenticationToken("rod", "äöü");
399+
rodRequest.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest()));
400+
Authentication rod = new UsernamePasswordAuthenticationToken("rod", "äöü", AuthorityUtils.createAuthorityList("ROLE_1"));
401+
402+
manager = mock(AuthenticationManager.class);
403+
when(manager.authenticate(rodRequest)).thenReturn(rod);
404+
when(manager.authenticate(not(eq(rodRequest)))).thenThrow(new BadCredentialsException(""));
405+
406+
filter = new BasicAuthenticationFilter(manager, new BasicAuthenticationEntryPoint());
407+
filter.setCredentialsCharset("ISO-8859-1");
408+
409+
String token = "rod:äöü";
410+
MockHttpServletRequest request = new MockHttpServletRequest();
411+
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes(StandardCharsets.UTF_8))));
412+
request.setServletPath("/some_file.html");
413+
414+
MockHttpServletResponse response = new MockHttpServletResponse();
415+
416+
// Test
417+
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
418+
FilterChain chain = mock(FilterChain.class);
419+
420+
filter.doFilter(request, response, chain);
421+
422+
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
423+
verify(chain, never()).doFilter(any(ServletRequest.class), any(ServletResponse.class));
424+
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
425+
}
426+
323427
}

0 commit comments

Comments
 (0)