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
(id="applicationConversionService")
pada contohSementara Ralphs Answer memberikan solusi yang elegan, dengan Spring Security 3.2 Anda tidak perlu lagi mengimplementasikannya sendiri
ArgumentResolver
.Jika Anda memiliki
UserDetails
implementasiCustomUser
, Anda bisa melakukan ini:Lihat Dokumentasi Spring Security: @AuthenticationPrincipal
sumber
@EnableWebMvcSecurity
atau dalam XML:<mvc:annotation-driven> <mvc:argument-resolvers> <bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver" /> </mvc:argument-resolvers> </mvc:annotation-driven>
customUser
itu nol atau tidak?if (customUser != null) { ... }
Spring Security dimaksudkan untuk bekerja dengan kerangka kerja non-Spring lainnya, oleh karena itu ia tidak terintegrasi dengan Spring MVC. Spring Security mengembalikan
Authentication
objek dariHttpServletRequest.getUserPrincipal()
metode secara default sehingga itulah yang Anda dapatkan sebagai prinsipal. Anda dapat memperolehUserDetails
objek Anda langsung dari ini dengan menggunakanPerhatikan juga bahwa tipe objek dapat bervariasi tergantung pada mekanisme otentikasi yang digunakan (misalnya, Anda mungkin tidak mendapatkan
UsernamePasswordAuthenticationToken
) dan objek yangAuthentication
tidak harus berisi aUserDetails
. Ini bisa berupa string atau jenis lainnya.Jika Anda tidak ingin menelepon
SecurityContextHolder
secara langsung, pendekatan yang paling elegan (yang akan saya ikuti) adalah menyuntikkan antarmuka pengakses konteks keamanan kustom Anda sendiri yang disesuaikan dengan kebutuhan dan jenis objek pengguna. Buat antarmuka, dengan metode yang relevan, misalnya:Anda kemudian dapat mengimplementasikan ini dengan mengakses
SecurityContextHolder
implementasi standar Anda, sehingga memisahkan kode Anda dari Spring Security sepenuhnya. Kemudian menyuntikkan ini ke pengontrol yang membutuhkan akses ke informasi keamanan atau informasi pada pengguna saat ini.Manfaat utama lainnya adalah mudah untuk membuat implementasi sederhana dengan data tetap untuk pengujian, tanpa harus khawatir tentang populasi thread-lokal dan sebagainya.
sumber
Menerapkan
HandlerInterceptor
antarmuka, lalu menyuntikkanUserDetails
ke setiap permintaan yang memiliki Model, sebagai berikut:sumber
<mvc:interceptors>
file konfigurasi aplikasi saya.spring-security-taglibs
: stackoverflow.com/a/44373331/548473Dimulai dengan Spring Security versi 3.2, fungsionalitas khusus yang telah diterapkan oleh beberapa jawaban yang lebih lama, ada di luar kotak dalam bentuk
@AuthenticationPrincipal
anotasi yang didukung olehAuthenticationPrincipalArgumentResolver
.Contoh sederhana penggunaannya adalah:
CustomUser perlu ditugaskan dari
authentication.getPrincipal()
Berikut adalah Javadocs yang sesuai dari AuthenticationPrincipal dan AuthenticationPrincipalArgumentResolver
sumber
sumber
Dan jika Anda membutuhkan pengguna yang berwenang dalam template (misalnya JSP) gunakan
bersama dengan
sumber
Anda dapat mencoba ini: Dengan Menggunakan Objek Otentikasi dari Spring kita bisa mendapatkan rincian Pengguna dari itu dalam metode controller. Di bawah ini adalah contoh, dengan meneruskan objek Otentikasi dalam metode pengontrol bersama dengan argumen. Setelah pengguna diautentikasi detailnya terisi dalam Objek Otentikasi.
sumber