Pendahuluan Dasar Keamanan Musim Semi
Saya tidak akan memberikan terlalu banyak pengantar keamanan musim semi di sini. Untuk detailnya, silakan merujuk ke dokumentasi resmi.
Saya hanya akan berbicara tentang fungsi inti dari SpringSecurity:
Konstruksi Lingkungan Dasar
Di sini kami menggunakan Springboot sebagai kerangka dasar proyek. Saya menggunakan metode Maven untuk manajemen paket, jadi di sini kami pertama -tama memberikan metode mengintegrasikan keamanan musim semi.
<Dependencies> ... <dependency> <GroupId> org.springframework.boot </groupid> <ArTifactId> Spring-boot-starter-Security </t Artifactid> </dependency> ... </dependensi>
Kemudian buat antarmuka permintaan lapisan web
@Restcontroller @requestMapping ("/user") kelas publik usercontroller {@getmapping string publik getUsers () {return "hello spring security"; }}Selanjutnya, Anda dapat menjalankan proyek secara langsung dan memanggil antarmuka untuk melihat efeknya.
Memanggil melalui halaman web
Pertama -tama kami melakukan panggilan antarmuka melalui browser dan secara langsung mengakses http: // localhost: 8080/pengguna. Jika antarmuka dapat diakses secara normal, maka "Hello Spring Security" harus ditampilkan.
Tetapi kami tidak dapat mengaksesnya secara normal, dan kotak input otentikasi pada gambar di bawah ini muncul
Ini karena di Springboot, keamanan musim semi default efektif. Pada saat ini, antarmuka dilindungi dan kita perlu melewati verifikasi untuk mengaksesnya secara normal. Spring Security menyediakan pengguna default, nama pengguna adalah pengguna, dan kata sandi secara otomatis dihasilkan ketika proyek dimulai.
Saat kami memeriksa log startup proyek, kami akan menemukan log berikut
Menggunakan Kata Sandi Keamanan Default: 62ccf9ca-9FBE-4993-8566-8468CC3C28C
Tentu saja, kata sandi yang Anda lihat harus berbeda dari milik saya. Kami langsung masuk dengan pengguna dan kata sandi di log startup.
Setelah masuk dengan sukses, Anda melompat ke halaman di mana antarmuka disebut secara normal.
Jika Anda tidak ingin mengaktifkan keamanan musim semi dari awal, Anda dapat mengonfigurasi yang berikut dalam file konfigurasi:
# Keamanan Mengaktifkan Security.basic.enabled = False
Kotak login yang baru saja saya lihat disediakan oleh Springsecurity, yang disebut httpbasiclogin. Bukan itu yang kami inginkan pada produk kami. Front-end kami umumnya melakukan verifikasi login pengguna melalui pengiriman formulir, jadi kami perlu menyesuaikan logika otentikasi kami sendiri.
Kustomisasi logika otentikasi pengguna
Setiap sistem harus memiliki set sistem pengguna sendiri, jadi kami perlu menyesuaikan logika otentikasi dan antarmuka login kami sendiri.
Di sini kita perlu mengkonfigurasi SPRINGSECURITY sesuai
@ConfigurationPublic kelas browerersecurityconfig memperluas websecurityconfigurerAdapter {@override void configure (httpsecurity http) melempar pengecualian {http.formlogin () // menentukan halaman login yang akan ditransfer ketika pengguna diperlukan untuk masuk. dilindungi dan mana yang tidak perlu dilindungi. }}Selanjutnya, konfigurasikan logika otentikasi pengguna, karena kami memiliki sistem pengguna kami sendiri.
@ComponentPublic kelas myUserDetailsService mengimplementasikan userDetailsService {private Logger Logger = LoggerFactory.getLogger (getClass ()); @Override Public UserDetails LoadUserByUserName (String Username) melempar UserNamenotFoundException {Logger.info ("User's Username: {}", username); // TODO Menurut nama pengguna, temukan kata sandi yang sesuai, dan merangkum informasi pengguna dan pengembalian. Parameter adalah: nama pengguna, kata sandi, izin pengguna pengguna pengguna = pengguna baru (userame, "123456", otoritas. Pengguna Kembali; }} Kami tidak melakukan terlalu banyak verifikasi di sini. Nama pengguna dapat diisi sesuka hati, tetapi kata sandi harus "123456" sehingga kami dapat masuk dengan sukses.
Pada saat yang sama, kita dapat melihat bahwa parameter ketiga dari objek pengguna di sini mewakili izin dari pengguna saat ini, dan kami mengaturnya ke "admin".
Jalankan program untuk mengujinya, dan Anda akan menemukan bahwa antarmuka login telah berubah.
Ini karena kami mengonfigurasi http.formLogin() di file konfigurasi
Mari kita isi pengguna di sini, lalu isi versi yang salah (non-123456). Ini akan mendorong kesalahan verifikasi:
Pada saat yang sama, di konsol, pengguna yang baru saja Anda isi ketika Anda masuk juga akan dicetak.
Sekarang mari kita coba masuk dengan kata sandi yang benar. Anda dapat menemukan bahwa itu akan melewati verifikasi dan melompat ke halaman panggilan antarmuka yang benar.
UserDetails
Baru saja, ketika kami menulis MyUserDetailsService , kami menerapkan metode dan mengembalikan UserDetails . Pengguna ini adalah objek yang merangkum informasi pengguna, yang berisi tujuh metode
Antarmuka Publik UserDetails memperluas serial {// pengumpulan informasi izin yang dienkapsulasi <? memperluas Grantedauthority> getAuthoritys (); // informasi kata sandi string getPassword (); // Login nama pengguna getUserName (); // apakah akun itu berakhir boolean isaccountnonexpired (); // apakah akun itu beku boolean isaccountnonlocked (); // Apakah kata sandi akun berakhir, umumnya beberapa sistem dengan persyaratan kata sandi tinggi akan menggunakannya. Dibandingkan dengan pengguna diharuskan untuk mengatur ulang kata sandi sesekali boolean iscredentialsnonexpired (); // Apakah akunnya tersedia? boolean isenabled ();}Saat kami mengembalikan pengguna kelas implementasi pengguna, kami dapat mengatur parameter yang sesuai melalui metode konstruktor pengguna
Enkripsi dan dekripsi kata sandi
Ada antarmuka kata sandi di springs cecure
Public Interface PasswordEncoder {// Enkripsi Kata Sandi String Encode (CharSequence Var1); // Tentukan kata sandi agar sesuai dengan kecocokan boolean (charsequence var1, string var2);} Kami hanya perlu mengimplementasikan antarmuka ini sendiri dan mengkonfigurasinya di file konfigurasi.
Di sini saya akan mengujinya sementara dengan kelas implementasi yang disediakan secara default
// BrowersecurityConfig @BeanPublic PasswordEncoder PasswordEncoder () {return baru bcryptpasswordEncoder (); }Penggunaan enkripsi:
@ComponentPublic kelas myUserDetailsService mengimplementasikan userDetailsService {private Logger Logger = LoggerFactory.getLogger (getClass ()); @Autowired Private PasswordEncoder Kata SandiCoder; @Override Public UserDetails LoadUserByUserName (String Username) melempar UserNamenotFoundException {Logger.info ("User's Username: {}", username); String password = passwordEncoder.encode ("123456"); logger.info ("kata sandi: {}", kata sandi); // Parameternya adalah: nama pengguna, kata sandi, izin pengguna pengguna pengguna = pengguna baru (nama pengguna, kata sandi, otoritas. Pengguna Kembali; }}Di sini kami hanya mengenkripsi 123456. Kami dapat melakukan tes dan menemukan bahwa kata sandi yang dicetak setiap kali berbeda. Ini adalah peran dari bcryptpasswordEncoder yang dikonfigurasi.
Logika otentikasi pengguna yang dipersonalisasi
Halaman login khusus
Dalam tes sebelumnya, antarmuka login default selalu digunakan. Saya percaya bahwa setiap produk memiliki desain antarmuka login sendiri, jadi kami akan belajar tentang cara menyesuaikan halaman login di bagian ini.
Mari Tulis Halaman Login Sederhana Dulu
<! Doctype html> <html lang = "en"> <head> <meta charset = "utf-8"> <itement> halaman login </iteme> </head> <hody> <h2> Halaman login khusus </h2> <bentuk acti type="text" name="username"></td> </tr> <tr> <td>Password:</td> <td><input type="password" name="password"></td> </tr> <tr> <td colspan="2"><button type="submit">Login</button></td> </tr> </table> </form> </body> </html>
Setelah menyelesaikan halaman login, Anda perlu mengonfigurasinya untuk SPRINGSECURTY
// browersecurityconfig.java@overrideprotected void configure (httpsecurity http) melempar pengecualian {http.FormLogin () // Tentukan halaman login yang akan ditransfer ke ketika pengguna perlu masuk .LoginPage ("/LOGIN.html")/ page.loginprocessingurl ("/user/login") // custom login antarmuka.and () .AuthorizeRequests () // Tentukan URL mana yang perlu dilindungi dan mana yang tidak perlu dilindungi. .authenticated () .and () .csrf (). Disable (); // matikan perlindungan CSRF}Dengan cara ini, setiap kali kami mengakses antarmuka yang dilindungi, kami akan ditransfer ke halaman login.html
Menangani berbagai jenis permintaan
Karena sekarang, ujung depan dan belakang umumnya dipisahkan, ujung belakang menyediakan antarmuka untuk ujung depan untuk memanggil dan mengembalikan data format JSON ke ujung depan. Seperti sebelumnya, antarmuka yang dilindungi dipanggil dan lompatan halaman secara langsung dialihkan. Ini dapat diterima di sisi web, tetapi tidak mungkin di sisi aplikasi, jadi kita perlu melakukan pemrosesan lebih lanjut.
Inilah ide sederhana yang disortir
Pertama, tulis pengontrol khusus dan lompat ke sana saat otentikasi identitas diperlukan.
@RestControllerPublic Class BrowserSecurityController {private Logger Logger = loggerFactory.getLogger (getClass ()); // caching dan pemulihan Informasi permintaan asli Private REQUESTCACHE requestCache = httpsessionRequestCache baru (); // Digunakan untuk mengarahkan kembali redirectstrategy pribadi redirectstrategy = New DeFaultredirectStrategy (); /** * When identity authentication is required, jump over* @param request * @param response * @return */ @RequestMapping("/authentication/require") @ResponseStatus(code = HttpStatus.UNAUTHORIZED) public BaseResponse requiresAuthenication(HttpServletRequest request, HttpServletResponse response) throws IOException { SaveDRequest SaveDRequest = RequestCache.getRequest (Request, Response); if (saveDRequest! = null) {string targetUrl = saveDrequest.getRedirecturl (); logger.info ("Permintaan untuk memicu lompatan adalah:" + targetUrl); if (stringutils.endswithignorecase (targetUrl, ".html")) {redirectstrategy.sendredirect (permintaan, respons, "/login.html"); }} return new Baseresponse ("Layanan yang diakses membutuhkan otentikasi identitas, harap pandu pengguna ke halaman login"); }}Tentu saja, file konfigurasi perlu dimodifikasi sesuai, jadi saya tidak akan memposting kode di sini. Itu untuk membuka antarmuka.
Ekstensi:
Di sini kita menulis antarmuka yang diakses dari halaman web, lalu melompat ke halaman "/Login.html". Bahkan, kami dapat memperluasnya dan mengkonfigurasi alamat lompatan ke file konfigurasi, yang akan lebih nyaman.
Login pemrosesan khusus berhasil/gagal
Dalam tes sebelumnya, pengalihan halaman dilakukan setelah login yang berhasil.
Dalam hal pemisahan ujung depan dan belakang, jika kita masuk dengan sukses, kita mungkin perlu mengembalikan informasi pribadi pengguna ke ujung depan alih -alih melompat langsung. Hal yang sama berlaku untuk login yang gagal.
Ini melibatkan dua antarmuka dalam AuthenticationSuccessHandler keamanan musim semi yang bersikap handler dan AuthenticationFailureHandler . Kami dapat mengimplementasikan antarmuka ini dan mengonfigurasinya. Tentu saja, kerangka kerja memiliki kelas implementasi default. Kami dapat mewarisi kelas implementasi ini dan menyesuaikan bisnis kami
@Component ("myAuthenCtiationsuccessHandler") kelas publik myauthenctiationsuccesshandler memperluas SimpleUrlAuthenticationsuccessHandler {private Logger Logger = LoggerFactory.getLogger (getClass ()); @Autowired Private ObjectMapper ObjectMapper; @Override public void onAuthenticationsuccess (permintaan httpservletRequest, respons httpservletResponse, otentikasi otentikasi) melempar ioException, servletException {logger.info ("Login Success"); response.setContentType ("Application/JSON; charset = UTF-8"); response.getWriter (). write (objectMapper.writevalueAsstring (otentikasi)); }} Di sini kami mengembalikan string JSON melalui respons.
Parameter ketiga dalam metode ini, Authentication , berisi informasi pengguna login (userDetails), informasi sesi, informasi login, dll.
@Component ("myauthenctiationfailureureHandler") kelas publik myauthenctiationfailureHandler memperluas SimpleUrlAuthenticationFailureHandler {private Logger Logger = LoggerFactory.GetLogger (getClass ()); @Autowired Private ObjectMapper ObjectMapper; @Override public void onAuthenticationFailure (permintaan httpservletRequest, respons httpservletResponse, pengecualian AuthenticationException) melempar ioException, ServletException {Logger.info ("Login Gagal"); response.setstatus (httpstatus.internal_server_error.value ()); response.setContentType ("Application/JSON; charset = UTF-8"); response.getWriter (). write (objectMapper.writevalueAsstring (new baseresponse (exception.getMessage ()))); }} Parameter ketiga dalam metode ini AuthenticationException , termasuk informasi tentang kegagalan login.
Demikian pula, masih perlu untuk mengonfigurasinya di file konfigurasi. Saya tidak akan memposting semua kode di sini, hanya pernyataan yang sesuai yang diposting.
.successhandler (myauthenticationsuccesshandler) // login khusus berhasil menangani.
Kode
Anda dapat mengklik saya untuk melihat kode lengkap
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.