@@ -503,6 +503,126 @@ open fun findMessagesForUser(@CurrentUser customUser: CustomUser?): ModelAndView
503
503
----
504
504
======
505
505
506
+ Once it is a meta-annotation, parameterization is also available to you.
507
+
508
+ For example, consider when you have a JWT as your principal and you want to say which claim to retrieve.
509
+ As a meta-annotation, you might do:
510
+
511
+ [tabs]
512
+ ======
513
+ Java::
514
+ +
515
+ [source,java,role="primary"]
516
+ ----
517
+ @Target({ElementType.PARAMETER, ElementType.TYPE})
518
+ @Retention(RetentionPolicy.RUNTIME)
519
+ @Documented
520
+ @AuthenticationPrincipal(expression = "claims['sub']")
521
+ public @interface CurrentUser {}
522
+ ----
523
+
524
+ Kotlin::
525
+ +
526
+ [source,kotlin,role="secondary"]
527
+ ----
528
+ @Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE)
529
+ @Retention(AnnotationRetention.RUNTIME)
530
+ @MustBeDocumented
531
+ @AuthenticationPrincipal(expression = "claims['sub']")
532
+ annotation class CurrentUser
533
+ ----
534
+ ======
535
+
536
+ which is already quite powerful.
537
+ But, it is also limited to retrieving the `sub` claim.
538
+
539
+ To make this more flexible, first publish the `AnnotationTemplateExpressionDefaults` bean like so:
540
+
541
+ [tabs]
542
+ ======
543
+ Java::
544
+ +
545
+ [source,java,role="primary"]
546
+ ----
547
+ @Bean
548
+ public AnnotationTemplateExpressionDefaults templateDefaults() {
549
+ return new AnnotationTemplateExpressionDeafults();
550
+ }
551
+ ----
552
+
553
+ Kotlin::
554
+ +
555
+ [source,kotlin,role="secondary"]
556
+ ----
557
+ @Bean
558
+ fun templateDefaults(): AnnotationTemplateExpressionDefaults {
559
+ return AnnotationTemplateExpressionDeafults()
560
+ }
561
+ ----
562
+
563
+ Xml::
564
+ +
565
+ [source,xml,role="secondary"]
566
+ ----
567
+ <b:bean name="annotationExpressionTemplateDefaults" class="org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults"/>
568
+ ----
569
+ ======
570
+
571
+ and then you can supply a parameter to `@CurrentUser` like so:
572
+
573
+ [tabs]
574
+ ======
575
+ Java::
576
+ +
577
+ [source,java,role="primary"]
578
+ ----
579
+ @Target({ElementType.PARAMETER, ElementType.TYPE})
580
+ @Retention(RetentionPolicy.RUNTIME)
581
+ @Documented
582
+ @AuthenticationPrincipal(expression = "claims['{claim}']")
583
+ public @interface CurrentUser {
584
+ String claim() default 'sub';
585
+ }
586
+ ----
587
+
588
+ Kotlin::
589
+ +
590
+ [source,kotlin,role="secondary"]
591
+ ----
592
+ @Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE)
593
+ @Retention(AnnotationRetention.RUNTIME)
594
+ @MustBeDocumented
595
+ @AuthenticationPrincipal(expression = "claims['{claim}']")
596
+ annotation class CurrentUser(val claim: String = "sub")
597
+ ----
598
+ ======
599
+
600
+ This will allow you more flexibility across your set of applications in the following way:
601
+
602
+ [tabs]
603
+ ======
604
+ Java::
605
+ +
606
+ [source,java,role="primary"]
607
+ ----
608
+ @RequestMapping("/messages/inbox")
609
+ public ModelAndView findMessagesForUser(@CurrentUser("user_id") String userId) {
610
+
611
+ // .. find messages for this user and return them ...
612
+ }
613
+ ----
614
+
615
+ Kotlin::
616
+ +
617
+ [source,kotlin,role="secondary"]
618
+ ----
619
+ @RequestMapping("/messages/inbox")
620
+ open fun findMessagesForUser(@CurrentUser("user_id") userId: String?): ModelAndView {
621
+
622
+ // .. find messages for this user and return them ...
623
+ }
624
+ ----
625
+ ======
506
626
507
627
[[mvc-async]]
508
628
== Spring MVC Async Integration
0 commit comments