คำนำ:ตั้งแต่ Spring-Security 3.2 มีคำอธิบายประกอบที่ดี@AuthenticationPrincipal
อธิบายอธิบายไว้ในตอนท้ายของคำตอบนี้ นี่เป็นวิธีที่ดีที่สุดเมื่อคุณใช้ Spring-Security> = 3.2
เมื่อคุณ:
- ใช้ Spring-Security เวอร์ชั่นที่เก่ากว่า
- จำเป็นต้องโหลดวัตถุผู้ใช้ที่กำหนดเองของคุณจากฐานข้อมูลโดยข้อมูลบางอย่าง (เช่นการเข้าสู่ระบบหรือรหัส) ที่เก็บไว้ในเงินต้นหรือ
- ต้องการเรียนรู้วิธีการ
HandlerMethodArgumentResolver
หรือWebArgumentResolver
สามารถแก้ปัญหานี้ในวิธีที่สง่างามหรือเพียงแค่ต้องการเรียนรู้พื้นหลัง@AuthenticationPrincipal
และAuthenticationPrincipalArgumentResolver
(เพราะมันขึ้นอยู่กับHandlerMethodArgumentResolver
)
จากนั้นอ่านต่อไป - ใช้อย่างอื่น@AuthenticationPrincipal
และขอขอบคุณ Rob Winch (ผู้เขียน@AuthenticationPrincipal
) และLukas Schmelzeisen (สำหรับคำตอบของเขา)
(BTW: คำตอบของฉันเก่ากว่านิดหน่อย (มกราคม 2555) ดังนั้นจึงเป็นLukas Schmelzeisenที่ขึ้นมาเป็นคนแรกที่มี@AuthenticationPrincipal
โซลูชันคำอธิบายประกอบบน Spring Security 3.2)
จากนั้นคุณสามารถใช้ในตัวควบคุมของคุณ
public ModelAndView someRequestHandler(Principal principal) {
User activeUser = (User) ((Authentication) principal).getPrincipal();
...
}
มันก็โอเคถ้าคุณต้องการมันอีกครั้ง แต่ถ้าคุณต้องการมันหลาย ๆ ครั้งมันน่าเกลียดเพราะมันทำให้ตัวควบคุมมลพิษของคุณมีรายละเอียดโครงสร้างพื้นฐานซึ่งโดยปกติแล้วกรอบดังกล่าวควรจะถูกซ่อนไว้
ดังนั้นสิ่งที่คุณอาจต้องการคือมีตัวควบคุมดังนี้:
public ModelAndView someRequestHandler(@ActiveUser User activeUser) {
...
}
WebArgumentResolver
ดังนั้นคุณจะต้องดำเนินการ มันมีวิธี
Object resolveArgument(MethodParameter methodParameter,
NativeWebRequest webRequest)
throws Exception
ที่ได้รับการร้องขอจากเว็บ (พารามิเตอร์ที่สอง) และจะต้องส่งกลับUser
ถ้ารู้สึกรับผิดชอบต่อการโต้แย้งวิธี (พารามิเตอร์แรก)
ตั้งแต่ฤดูใบไม้ผลิ 3.1 HandlerMethodArgumentResolver
มีแนวคิดใหม่ที่เรียกว่า ถ้าคุณใช้ Spring 3.1+ คุณควรใช้มัน (อธิบายไว้ในหัวข้อถัดไปของคำตอบนี้))
public class CurrentUserWebArgumentResolver implements WebArgumentResolver{
Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) {
if(methodParameter is for type User && methodParameter is annotated with @ActiveUser) {
Principal principal = webRequest.getUserPrincipal();
return (User) ((Authentication) principal).getPrincipal();
} else {
return WebArgumentResolver.UNRESOLVED;
}
}
}
คุณต้องกำหนดคำอธิบายประกอบที่กำหนดเอง - คุณสามารถข้ามมันได้หากทุกอินสแตนซ์ของผู้ใช้ควรนำมาจากบริบทความปลอดภัยเสมอ แต่ไม่เคยเป็นวัตถุคำสั่ง
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActiveUser {}
ในการกำหนดค่าคุณจะต้องเพิ่มสิ่งนี้:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
id="applicationConversionService">
<property name="customArgumentResolver">
<bean class="CurrentUserWebArgumentResolver"/>
</property>
</bean>
@See: เรียนรู้วิธีกำหนดอาร์กิวเมนต์เมธอด Spring MVC @Controller
ควรสังเกตว่าถ้าคุณใช้ Spring 3.1 พวกเขาแนะนำ HandlerMethodArgumentResolver ผ่าน WebArgumentResolver - ดูความคิดเห็นโดยเจย์
เช่นเดียวกันกับHandlerMethodArgumentResolver
สำหรับ Spring 3.1+
public class CurrentUserHandlerMethodArgumentResolver
implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return
methodParameter.getParameterAnnotation(ActiveUser.class) != null
&& methodParameter.getParameterType().equals(User.class);
}
@Override
public Object resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
if (this.supportsParameter(methodParameter)) {
Principal principal = webRequest.getUserPrincipal();
return (User) ((Authentication) principal).getPrincipal();
} else {
return WebArgumentResolver.UNRESOLVED;
}
}
}
ในการกำหนดค่าคุณจะต้องเพิ่มสิ่งนี้
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="CurrentUserHandlerMethodArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
@See การใช้ประโยชน์จากอินเตอร์เฟสSpring MVC 3.1 HandlerMethodArgumentResolver
โซลูชั่น Spring-Security 3.2
Spring Security 3.2 (อย่าสับสนกับ Spring 3.2) มีโซลูชันบิลด์อิน: @AuthenticationPrincipal
( org.springframework.security.web.bind.annotation.AuthenticationPrincipal
) นี่คือคำอธิบายอย่างดีในคำตอบของ Lukas Schmelzeisen
มันเป็นแค่การเขียน
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
ในการทำให้การทำงานนี้คุณต้องลงทะเบียนAuthenticationPrincipalArgumentResolver
( org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver
): โดย "เปิดใช้งาน" @EnableWebMvcSecurity
หรือโดยการลงทะเบียน bean นี้ภายในmvc:argument-resolvers
- วิธีเดียวกับที่ฉันอธิบายด้วยโซลูชันพฤษภาคม 3.1 ของ Spring ด้านบน
การอ้างอิง @See Spring Security 3.2 บทที่ 11.2 @AuthenticationPrincipal
โซลูชัน Spring-Security 4.0
ใช้งานได้เหมือนโซลูชัน Spring 3.2 แต่ใน Spring 4.0 @AuthenticationPrincipal
และAuthenticationPrincipalArgumentResolver
ถูก "ย้าย" ไปยังแพ็คเกจอื่น:
(แต่คลาสเก่าในแพ็คเกจเก่ายังคงมีอยู่ดังนั้นอย่าผสมกัน!)
มันเป็นแค่การเขียน
import org.springframework.security.core.annotation.AuthenticationPrincipal;
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
เพื่อให้การทำงานนี้คุณต้องลงทะเบียน ( org.springframework.security.web.method.annotation.
) AuthenticationPrincipalArgumentResolver
: โดย "เปิดใช้งาน" @EnableWebMvcSecurity
หรือโดยการลงทะเบียน bean นี้ภายในmvc:argument-resolvers
- วิธีเดียวกับที่ฉันอธิบายด้วยโซลูชันพฤษภาคม 3.1 ของ Spring ด้านบน
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
@See Spring Security 5.0 อ้างอิงตอนที่ 39.3 @AuthenticationPrincipal