Pendaftaran dan log masuk boleh dikatakan sebagai perkara yang paling biasa dalam pembangunan harian, tetapi secara amnya selepas memasuki syarikat, fungsi seperti ini mempunyai telah lama tersedia Pembangunan telah siap, melainkan ia adalah projek baharu. Dalam dua hari yang lalu, saya kebetulan menghadapi keperluan sedemikian untuk melengkapkan fungsi pendaftaran dan log masuk di bahagian PC.
Terdapat banyak cara untuk mencapai keperluan sedemikian: seperti
1) HandlerInterceptor+WebMvcConfigurer+ThreadLocal
2) Penapis
3) Rangka Kerja Keselamatan Shiro (rangka kerja ringan)
4) Rangka kerja keselamatan Spring Security (rangka kerja berat)
Dan saya menggunakan teknologi Spring HandlerInterceptor+WebMvcConfigurer+ThreadLocal yang pertama untuk melaksanakannya.
HandlerInterceptor ialah antara muka yang disediakan untuk pemintas dalam springMVC, serupa dengan penapis Penapis dalam pembangunan Servlet, digunakan untuk pra-pemprosesan pemproses Untuk pemprosesan dan pasca pemprosesan, tiga kaedah perlu ditulis semula.
praHandle:
Masa panggilan: sebelum pemprosesan kaedah pengawal
Perintah pelaksanaan: Dalam kes Pemindas berantai, Pemindas dilaksanakan satu demi satu dalam susunan pengisytiharan
Jika palsu dikembalikan, pelaksanaan akan terganggu Nota: ia tidak akan masuk selepas Selesai
postHandle:
Premis panggilan: preHandle mengembalikan benar
Masa panggilan. : Selepas kaedah Pengawal diproses, DispatcherServlet Sebelum memberikan paparan, iaitu, ModelAndView boleh dikendalikan dalam kaedah ini
Perintah pelaksanaan: Dalam kes Pemintas berantai, Pemindas dilaksanakan dalam susunan pengisytiharan
Catatan: Walaupun postHandle bermula dengan post , tetapi kedua-dua permintaan pos dan mendapatkan permintaan boleh diproses
selepas Selesai:
Premis panggilan: preHandle mengembalikan benar
Masa panggilan: selepas DispatcherServlet memaparkan paparan
Kebanyakannya digunakan untuk membersihkan sumber
Kelas konfigurasi WebMvcConfigurer sebenarnya ialah kaedah konfigurasi dalamanSpring
, menggunakan bentukJavaBean
untuk menggantikan borang fail konfigurasi tradisionalxml
Untuk menyesuaikan rangka kerja, anda boleh menyesuaikan beberapa Pengendali, Pemindas, ViewResolver dan MessageConverter. Berdasarkan konfigurasi spring mvc berasaskan java, anda perlu membuat kelas konfigurasi dan melaksanakan antara mukaWebMvcConfigurer
dalam versi Spring Boot 1.5 bergantung pada penulisan semula kaedah WebMvcConfigurerAdapter untuk menambah pemintas tersuai dan Peranti penukaran mesej; dll. Selepas versi SpringBoot 2.0, kelas ini telah ditandakan @Deprecated (ditamatkan). Syor rasmi adalah untuk melaksanakan WebMvcConfigurer secara langsung atau mewarisi WebMvcConfigurationSupport secara langsung Kaedah pertama adalah untuk melaksanakan antara muka WebMvcConfigurer (disyorkan), dan kaedah kedua adalah untuk mewarisi kelas WebMvcConfigurationSupport
package com.liubujun.config; import com.liubujun.moudle.UserToken; import com.liubujun.util.SecurityContextUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.ws.handler.Handler; import java.io.IOException; /** * @Author: liubujun * @Date: 2022/5/21 16:12 */ @Component @Slf4j public class HeadTokenInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String authorization = request.getHeader("Authorization"); if (authorization == null ) { unauthorized(response); return false; } //这里一般都会解析出userToken的值,这里为了方便就直接new了 UserToken userToken = new UserToken(); SecurityContextUtil.addUser(userToken); return false; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { SecurityContextUtil.removeUser(); } private void unauthorized(HttpServletResponse response) { response.setStatus(HttpStatus.UNAUTHORIZED.value()); try { response.getWriter().append(HttpStatus.UNAUTHORIZED.getReasonPhrase()); } catch (IOException e) { log.error("HttpServletResponse writer error.msg",HttpStatus.UNAUTHORIZED.getReasonPhrase()); log.error(e.getMessage(),e); } } }
package com.liubujun.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.ArrayList; /** * @Author: liubujun * @Date: 2022/5/21 16:40 */ @Configuration public class MyWebMvcConfigurer extends WebMvcConfigurationSupport { @Autowired private HeadTokenInterceptor headTokenInterceptor; /** * 类似于白名单,在这边添加的请求不会走拦截器 * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { ArrayListpattres = new ArrayList<>(); pattres.add("/login/login"); registry.addInterceptor(headTokenInterceptor).excludePathPatterns(pattres).addPathPatterns("/**"); super.addInterceptors(registry); } /** * 添加静态资源 * @param registry */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("xxx.html") .addResourceLocations("classpath:/META-INF/resources"); super.addResourceHandlers(registry); } }
package com.liubujun.util; import com.liubujun.moudle.UserToken; import org.springframework.core.NamedThreadLocal; /** * @Author: liubujun * @Date: 2022/5/23 9:41 */ public class SecurityContextUtil { private static ThreadLocalthreadLocal = new NamedThreadLocal<>("user"); public static void addUser(UserToken user){ threadLocal.set(user); } public static UserToken getUser(){ return threadLocal.get(); } public static void removeUser(){ threadLocal.remove(); } public static String getPhoneNumber(){ return threadLocal.get().getPhoneNumber(); } public static Integer getId(){ return threadLocal.get().getId(); } public static String getUserText(){ return threadLocal.get().getUserText(); } }
5) Uji
Uji antara muka log masuk, (lead tanpa lulus token)
Uji antara muka lain, jika token tidak diluluskan, ia akan dipintas
Atas ialah kandungan terperinci Bagaimana SpringBoot melaksanakan pemintasan log masuk melalui ThreadLocal. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!