Rumah  >  Artikel  >  Java  >  Bagaimana SpringBoot melaksanakan pemintasan log masuk melalui ThreadLocal

Bagaimana SpringBoot melaksanakan pemintasan log masuk melalui ThreadLocal

WBOY
WBOYke hadapan
2023-05-22 12:04:421310semak imbas

    1 Pengenalan

    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.

    2 kelas konkrit

    2.1HandlerInterceptor

    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

    2.2 WebMvcConfigurer

    Kelas konfigurasi WebMvcConfigurer sebenarnya ialah kaedah konfigurasi dalaman Spring , menggunakan bentuk JavaBean untuk menggantikan borang fail konfigurasi tradisional xml 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 muka WebMvcConfigurer

    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

    3 Amalan kod

    1) Tulis pemintas HeadTokenInterceptor supaya ia mewarisi HandlerInterceptor

    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);
            }
        }
    }

    2) Tulis MyWebMvcConfigurer untuk mewarisi WebMvcConfigurationSupport

    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) {
            ArrayList<String> pattres = 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);
        }
    }

    3) Tulis Thread 4) Tulis pengawal ujian
    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 ThreadLocal<UserToken> threadLocal = 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)

    Bagaimana SpringBoot melaksanakan pemintasan log masuk melalui ThreadLocalUji 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!

    Kenyataan:
    Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam