Pembukaan: Sejak Spring-Security 3.2 ada penjelasan bagus yang @AuthenticationPrincipal
dijelaskan di akhir jawaban ini. Ini adalah cara terbaik untuk pergi ketika Anda menggunakan Spring-Security> = 3.2.
Ketika anda:
- menggunakan versi Spring-Security yang lebih lama,
- perlu memuat Objek Pengguna kustom Anda dari Database dengan beberapa informasi (seperti login atau id) yang disimpan di kepala sekolah atau
- ingin belajar bagaimana a
HandlerMethodArgumentResolver
atau WebArgumentResolver
dapat menyelesaikan ini dengan cara yang elegan, atau hanya ingin mempelajari latar belakang @AuthenticationPrincipal
dan AuthenticationPrincipalArgumentResolver
(karena didasarkan pada a HandlerMethodArgumentResolver
)
kemudian terus membaca - lain hanya menggunakan @AuthenticationPrincipal
dan terima kasih kepada Rob Winch (Penulis @AuthenticationPrincipal
) dan Lukas Schmelzeisen (untuk jawabannya).
(BTW: Jawaban saya sedikit lebih tua (Januari 2012), jadi Lukas Schmelzeisen yang muncul sebagai yang pertama dengan @AuthenticationPrincipal
basis solusi anotasi pada Spring Security 3.2.)
Kemudian Anda dapat menggunakan controller Anda
public ModelAndView someRequestHandler(Principal principal) {
User activeUser = (User) ((Authentication) principal).getPrincipal();
...
}
Tidak apa-apa jika Anda membutuhkannya sekali. Tetapi jika Anda membutuhkannya beberapa kali jelek karena itu mencemari controller Anda dengan detail infrastruktur, yang biasanya harus disembunyikan oleh kerangka kerja.
Jadi yang mungkin Anda inginkan adalah memiliki pengontrol seperti ini:
public ModelAndView someRequestHandler(@ActiveUser User activeUser) {
...
}
Karena itu Anda hanya perlu mengimplementasikan a WebArgumentResolver
. Ini memiliki metode
Object resolveArgument(MethodParameter methodParameter,
NativeWebRequest webRequest)
throws Exception
Itu mendapat permintaan web (parameter kedua) dan harus mengembalikan User
jika merasa bertanggung jawab atas argumen metode (parameter pertama).
Sejak Spring 3.1 ada konsep baru yang disebut HandlerMethodArgumentResolver
. Jika Anda menggunakan Spring 3.1+ maka Anda harus menggunakannya. (Dijelaskan di bagian selanjutnya dari jawaban ini))
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;
}
}
}
Anda perlu mendefinisikan Anotasi Khusus - Anda dapat mengabaikannya jika setiap instance Pengguna harus selalu diambil dari konteks keamanan, tetapi tidak pernah menjadi objek perintah.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActiveUser {}
Dalam konfigurasi Anda hanya perlu menambahkan ini:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
id="applicationConversionService">
<property name="customArgumentResolver">
<bean class="CurrentUserWebArgumentResolver"/>
</property>
</bean>
@Lihat: Belajar untuk menyesuaikan argumen metode Spring MVC @Controller
Perlu dicatat bahwa jika Anda menggunakan Spring 3.1, mereka merekomendasikan HandlerMethodArgumentResolver melalui WebArgumentResolver. - Lihat komentar oleh Jay
Sama dengan HandlerMethodArgumentResolver
untuk 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;
}
}
}
Dalam konfigurasi, Anda perlu menambahkan ini
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="CurrentUserHandlerMethodArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
@Lihat Memanfaatkan antarmuka Spring MVC 3.1 HandlerMethodArgumentResolver
Spring-Security 3.2 Solusi
Spring Security 3.2 (jangan bingung dengan Spring 3.2) memiliki solusi build in sendiri: @AuthenticationPrincipal
( org.springframework.security.web.bind.annotation.AuthenticationPrincipal
). Ini dijelaskan dengan baik dalam jawaban Lukas Schmelzeisen
Itu hanya menulis
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
Agar ini berfungsi, Anda harus mendaftarkan AuthenticationPrincipalArgumentResolver
( org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver
): baik dengan "mengaktifkan" @EnableWebMvcSecurity
atau dengan mendaftarkan kacang ini dalam mvc:argument-resolvers
- cara yang sama dengan yang saya jelaskan dengan solusi Spring 3.1 di atas.
@Lihat Spring Security 3.2 Referensi, Bab 11.2. @ OtentikasiPrincipal
Solusi Spring-Security 4.0
Ini bekerja seperti solusi Spring 3.2, tetapi di Spring 4.0 @AuthenticationPrincipal
dan AuthenticationPrincipalArgumentResolver
"dipindahkan" ke paket lain:
(Tapi kelas-kelas lama di paket-paket lamanya masih ada, jadi jangan campur mereka!)
Itu hanya menulis
import org.springframework.security.core.annotation.AuthenticationPrincipal;
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
Agar ini berfungsi, Anda harus mendaftarkan ( org.springframework.security.web.method.annotation.
) AuthenticationPrincipalArgumentResolver
: baik dengan "mengaktifkan" @EnableWebMvcSecurity
atau dengan mendaftarkan kacang ini dalam mvc:argument-resolvers
- cara yang sama dengan yang saya jelaskan dengan solusi Spring 3.1 di atas.
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
@Lihat Referensi Spring Security 5.0, Bab 39.3 @ OtentikasiPrincipal