Maison >Java >javaDidacticiel >Comment SpringBoot implémente l'interception de connexion via ThreadLocal
L'inscription et la connexion peuvent être considérées comme les choses les plus courantes dans le développement quotidien, mais généralement après l'entrée dans l'entreprise, des fonctions comme celle-ci ont été développées il y a longtemps, à moins qu'il ne s'agisse d'un nouveau projet. Au cours des deux derniers jours, j'ai rencontré un tel besoin de compléter la fonction d'enregistrement et de connexion côté PC.
Il existe de nombreuses façons de répondre à de tels besoins : comme
1) HandlerInterceptor+WebMvcConfigurer+ThreadLocal
2) Filtre de filtre
3) Cadre de sécurité Shiro (cadre léger)
4) Cadre de sécurité Spring Securety (cadre lourd)
Et j'utilise la première technologie Spring HandlerInterceptor+WebMvcConfigurer+ThreadLocal pour l'implémenter.
HandlerInterceptor est l'interface fournie pour les intercepteurs dans springMVC. Elle est similaire au filtre dans le développement de Servlet. Elle est utilisée pour le prétraitement et le post-traitement par le processeur.
preHandle :
Temps d'appel : avant le traitement de la méthode du contrôleur
Ordre d'exécution : dans le cas d'un Intercepteur chaîné, les Intercepteurs sont exécutés les uns après les autres dans l'ordre de déclaration
Si false est renvoyé, l'exécution sera interrompue. . Remarque : il n'entrera pas aprèsCompletion
postHandle :
Prémisse d'appel : preHandle renvoie true
Heure d'appel : après le traitement de la méthode Controller et avant que DispatcherServlet ne restitue la vue, c'est-à-dire que ModelAndView peut être utilisé dans cette méthode.
Ordre d'exécution : dans le cas d'un intercepteur chaîné, l'intercepteur est exécuté dans l'ordre de déclaration
Remarques : bien que postHandle commence par post, les demandes de publication et les demandes d'obtention peuvent être traitées
afterCompletion :
Prémisse d'appel : preHandle renvoie true
Temps d'appel : après que DispatcherServlet ait rendu la vue
Utilisations multiples Pour nettoyer les ressources
La classe de configuration WebMvcConfigurer est en fait une Spring
内部的一种配置方式,采用JavaBean
的形式来代替传统的xml
配置文件形式进行针对框架个性化定制,可以自定义一些Handler,Interceptor,ViewResolver,MessageConverter。基于java-based方式的spring mvc配置,需要创建一个配置类并实现WebMvcConfigurer
interface
Dans la version Spring Boot 1.5, nous nous appuyons sur la méthode de réécriture de WebMvcConfigurerAdapter ; pour ajouter des intercepteurs personnalisés, des convertisseurs de messages, etc. Après la version SpringBoot 2.0, cette classe a été marquée @Deprecated (obsolète). La recommandation officielle est d'implémenter directement WebMvcConfigurer ou d'hériter directement de WebMvcConfigurationSupport. La première méthode consiste à implémenter l'interface WebMvcConfigurer (recommandée), et la deuxième méthode consiste à hériter de la classe WebMvcConfigurationSupport
1) Écrivez l'intercepteur HeadTokenInterceptor dans hériter du 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) Écrivez MyWebMvcConfigurer pour le faire hériter de 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) Écrivez la classe ThreadLocal pour stocker les informations utilisateur
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(); } }
4) Écrivez un contrôleur de test
@RestController @RequestMapping(value = "/login",produces = {"application/json;charset=UTF-8"}) public class Login { @PostMapping("/login") public String login(){ return "登录请求不需要拦截"; } @PostMapping("/other") public String other(){ return "其他的请求需要拦截"; } }
5) Test
Testez l'interface de connexion, (libérez-le directement sans passer le token)
Testez d'autres interfaces, non Le token a été intercepté
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!