Skip to content

Commit 05e3f27

Browse files
committed
Consistently apply PrincipalMethodArgumentResolver
Closes gh-26117
1 parent a7cce64 commit 05e3f27

File tree

3 files changed

+61
-14
lines changed

3 files changed

+61
-14
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ protected List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
342342
resolvers.addAll(getCustomArgumentResolvers());
343343
}
344344

345+
// Catch-all
346+
resolvers.add(new PrincipalMethodArgumentResolver());
347+
345348
return resolvers;
346349
}
347350

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,7 @@ private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
681681
}
682682

683683
// Catch-all
684+
resolvers.add(new PrincipalMethodArgumentResolver());
684685
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
685686
resolvers.add(new ServletModelAttributeMethodProcessor(true));
686687

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterIntegrationTests.java

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,7 +16,12 @@
1616

1717
package org.springframework.web.servlet.mvc.method.annotation;
1818

19-
import java.awt.Color;
19+
import java.awt.*;
20+
import java.lang.annotation.Documented;
21+
import java.lang.annotation.ElementType;
22+
import java.lang.annotation.Retention;
23+
import java.lang.annotation.RetentionPolicy;
24+
import java.lang.annotation.Target;
2025
import java.lang.reflect.Method;
2126
import java.net.URI;
2227
import java.security.Principal;
@@ -70,13 +75,15 @@
7075
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
7176
import org.springframework.web.bind.support.SessionStatus;
7277
import org.springframework.web.bind.support.WebArgumentResolver;
78+
import org.springframework.web.bind.support.WebDataBinderFactory;
7379
import org.springframework.web.context.request.NativeWebRequest;
7480
import org.springframework.web.context.request.RequestContextHolder;
7581
import org.springframework.web.context.request.ServletWebRequest;
7682
import org.springframework.web.context.support.GenericWebApplicationContext;
7783
import org.springframework.web.method.HandlerMethod;
7884
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
7985
import org.springframework.web.method.support.InvocableHandlerMethod;
86+
import org.springframework.web.method.support.ModelAndViewContainer;
8087
import org.springframework.web.servlet.HandlerMapping;
8188
import org.springframework.web.servlet.ModelAndView;
8289
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
@@ -114,6 +121,7 @@ public void setup() throws Exception {
114121

115122
List<HandlerMethodArgumentResolver> customResolvers = new ArrayList<>();
116123
customResolvers.add(new ServletWebArgumentResolverAdapter(new ColorArgumentResolver()));
124+
customResolvers.add(new CustomPrincipalArgumentResolver());
117125

118126
GenericWebApplicationContext context = new GenericWebApplicationContext();
119127
context.refresh();
@@ -145,7 +153,7 @@ public void handle() throws Exception {
145153
Class<?>[] parameterTypes = new Class<?>[] {int.class, String.class, String.class, String.class, Map.class,
146154
Date.class, Map.class, String.class, String.class, TestBean.class, Errors.class, TestBean.class,
147155
Color.class, HttpServletRequest.class, HttpServletResponse.class, TestBean.class, TestBean.class,
148-
User.class, OtherUser.class, Model.class, UriComponentsBuilder.class};
156+
User.class, OtherUser.class, Principal.class, Model.class, UriComponentsBuilder.class};
149157

150158
String datePattern = "yyyy.MM.dd";
151159
String formattedDate = "2011.03.16";
@@ -214,6 +222,7 @@ public void handle() throws Exception {
214222
assertThat(model.get("customArg") instanceof Color).isTrue();
215223
assertThat(model.get("user").getClass()).isEqualTo(User.class);
216224
assertThat(model.get("otherUser").getClass()).isEqualTo(OtherUser.class);
225+
assertThat(((Principal) model.get("customUser")).getName()).isEqualTo("Custom User");
217226

218227
assertThat(model.get("sessionAttribute")).isSameAs(sessionAttribute);
219228
assertThat(model.get("requestAttribute")).isSameAs(requestAttribute);
@@ -476,16 +485,24 @@ public String handle(
476485
HttpServletResponse response,
477486
@SessionAttribute TestBean sessionAttribute,
478487
@RequestAttribute TestBean requestAttribute,
479-
User user,
488+
@Nullable User user, // gh-26117, gh-26117 (for @Nullable)
480489
@ModelAttribute OtherUser otherUser,
490+
@AuthenticationPrincipal Principal customUser, // gh-25780
481491
Model model,
482492
UriComponentsBuilder builder) {
483493

484-
model.addAttribute("cookie", cookieV).addAttribute("pathvar", pathvarV).addAttribute("header", headerV)
485-
.addAttribute("systemHeader", systemHeader).addAttribute("headerMap", headerMap)
486-
.addAttribute("dateParam", dateParam).addAttribute("paramMap", paramMap)
487-
.addAttribute("paramByConvention", paramByConvention).addAttribute("value", value)
488-
.addAttribute("customArg", customArg).addAttribute(user)
494+
model.addAttribute("cookie", cookieV)
495+
.addAttribute("pathvar", pathvarV)
496+
.addAttribute("header", headerV)
497+
.addAttribute("systemHeader", systemHeader)
498+
.addAttribute("headerMap", headerMap)
499+
.addAttribute("dateParam", dateParam)
500+
.addAttribute("paramMap", paramMap)
501+
.addAttribute("paramByConvention", paramByConvention)
502+
.addAttribute("value", value)
503+
.addAttribute("customArg", customArg)
504+
.addAttribute(user)
505+
.addAttribute("customUser", customUser)
489506
.addAttribute("sessionAttribute", sessionAttribute)
490507
.addAttribute("requestAttribute", requestAttribute)
491508
.addAttribute("url", builder.path("/path").build().toUri());
@@ -520,10 +537,15 @@ public String handleInInterface(
520537
Model model,
521538
UriComponentsBuilder builder) {
522539

523-
model.addAttribute("cookie", cookieV).addAttribute("pathvar", pathvarV).addAttribute("header", headerV)
524-
.addAttribute("systemHeader", systemHeader).addAttribute("headerMap", headerMap)
525-
.addAttribute("dateParam", dateParam).addAttribute("paramMap", paramMap)
526-
.addAttribute("paramByConvention", paramByConvention).addAttribute("value", value)
540+
model.addAttribute("cookie", cookieV)
541+
.addAttribute("pathvar", pathvarV)
542+
.addAttribute("header", headerV)
543+
.addAttribute("systemHeader", systemHeader)
544+
.addAttribute("headerMap", headerMap)
545+
.addAttribute("dateParam", dateParam)
546+
.addAttribute("paramMap", paramMap)
547+
.addAttribute("paramByConvention", paramByConvention)
548+
.addAttribute("value", value)
527549
.addAttribute("customArg", customArg).addAttribute(user)
528550
.addAttribute("sessionAttribute", sessionAttribute)
529551
.addAttribute("requestAttribute", requestAttribute)
@@ -598,7 +620,6 @@ public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest
598620
}
599621
}
600622

601-
602623
private static class User implements Principal {
603624

604625
@Override
@@ -616,4 +637,26 @@ public String getName() {
616637
}
617638
}
618639

640+
private static class CustomPrincipalArgumentResolver implements HandlerMethodArgumentResolver {
641+
642+
@Override
643+
public boolean supportsParameter(MethodParameter parameter) {
644+
return (Principal.class.isAssignableFrom(parameter.getParameterType()) &&
645+
parameter.hasParameterAnnotation(AuthenticationPrincipal.class));
646+
}
647+
648+
@Nullable
649+
@Override
650+
public Object resolveArgument(
651+
MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
652+
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) {
653+
654+
return (Principal) () -> "Custom User";
655+
}
656+
}
657+
658+
@Target({ ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
659+
@Retention(RetentionPolicy.RUNTIME)
660+
@Documented
661+
public @interface AuthenticationPrincipal {}
619662
}

0 commit comments

Comments
 (0)