[JAVA] Utilisez Interceptor au printemps

J'ai découvert l'intercepteur au printemps, je vais donc écrire un article.

Présentation de l'intercepteur

La classe Interceptor dans Spring est une classe utilisée lorsque, par exemple, "je veux implémenter une classe qui effectue un traitement commun avant que le contrôleur ne soit appelé". Par exemple, il est utilisé lorsque vous souhaitez authentifier l'utilisateur qui accède avant de mapper la demande.

Classe d'implémentation

Je vais expliquer brièvement la classe implémentée.

Classe d'intercepteur

TestInterceptor.java


import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.example.annotation.NonAuth;
import com.example.models.TestUser;
import com.example.service.UserPermissionService;

public class TestInterceptor extends HandlerInterceptorAdapter{

	@Autowired
	UserPermissionService service;

    @Override
    public boolean preHandle(
                    HttpServletRequest request,
                    HttpServletResponse response,
                    Object handler) throws Exception {

    	//False si la demande ne peut pas être mappée
    	if( handler instanceof HandlerMethod ) {

    		// @Vérifier si NonAuth est accordé
    		HandlerMethod hm = (HandlerMethod) handler;
            Method method = hm.getMethod();
            NonAuth annotation = AnnotationUtils.findAnnotation(method, NonAuth.class);
            if (annotation != null) {
                return true;
            }

            //Authentification d'utilisateur
	    	HttpSession session = request.getSession(false);
	    	try {
	    		TestUser user = (TestUser)session.getAttribute("user");
	    		if(!service.checkPermission(user)) {
	    			response.sendRedirect("/error");
	    			return false;
	    		}
	    	}catch(NullPointerException e){
	    		response.sendRedirect("/error");
	    		return false;
	    	}
	        return true;
    	}
    	response.sendRedirect("/error");
    	return false;
    }
}

-La classe Interceptor doit hériter de HandlerInterceptorAdaptor. -PreHandle () est une méthode qui est appelée avant que le processus du contrôleur ne soit appelé. Vous pouvez également remplacer postHandle (), qui est appelé une fois que le contrôleur a terminé le traitement, et afterCompletion (), qui est appelé une fois qu'une série de traitement de requête est terminée. -Retourne true si la demande est faite à une méthode avec l'annotation NonAuth en premier lieu (décrite plus loin). -Dans la classe ci-dessus, l'authentification de l'utilisateur est effectuée avec UserPermission.checkPermission (), et si la vérification est effectuée, l'écran est redirigé vers l'écran d'erreur (décrit plus loin). -Si le Handler passé n'est pas une instance de HandlerMethod, il redirigera vers l'écran d'erreur (décrit plus loin).

Classe de configuration

BeanConfiguration.java


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;

import com.example.interceptor.TestInterceptor;
import com.example.service.TestService;

@Configuration
public class BeanConfiguration {

	@Bean
	public HandlerInterceptor testInterceptor() throws Exception{
		return new TestInterceptor();
	}

}

-Définissez la classe Interceptor comme un bean.

Classe WebMvcConfig

WebMvcConfig.java


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

	@Autowired
    HandlerInterceptor testInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(testInterceptor);
    }
}

-Interceptor est une classe qui hérite de WebMvcConfigurer et doit être reconnue par Spring par addInterceptors (). -Appelez la classe Interceptor avec Autowired.

Classe de contrôleur

TestInterceptorController.java


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.example.annotation.NonAuth;
import com.example.models.TestUser;

@Controller
@RequestMapping("/interceptor")
public class TestInterceptorController {

	@RequestMapping(value="/index",method = RequestMethod.GET)
	@NonAuth
	public String index(Model model, HttpServletRequest request) {

		TestUser user = new TestUser();
		user.setName("Tanaka");

		HttpSession session = request.getSession(false);
		if (session == null){
			session = request.getSession(true);
			session.setAttribute("user", user);
		}else {
			session.setAttribute("user", user);
		}

		return "test/index";
	}

	@RequestMapping(value="/test", method=RequestMethod.GET)
	public String test(Model model) {
		model.addAttribute("msg", "HelloWorld!");
		return "test/test";
	}

}

-D'abord, lorsque vous accédez à l'index, l'utilisateur est enregistré dans la session. -Depuis que l'index a une annotation NonAuth, il passe l'authentification sans aucune question. -Vous devez effacer l'authentification pour accéder au test.

C'est la classe d'implémentation approximative.

Supplément

Si vous voulez qu'une méthode particulière renvoie toujours true dans preHandle ()

-Comme mentionné ci-dessus, il existe une méthode d'utilisation des annotations, par exemple. -Définissez l'annotation vous-même. -Je vérifie si la méthode a l'annotation définie dans preHandle () de la classe Interceptor. ・ S'il est donné, aucune question n'est posée et true est renvoyé. ・ J'ai fait référence au site suivant. https://qiita.com/dmnlk/items/cce551ce18973f013b36

Lorsque vous souhaitez passer à l'écran d'erreur lorsque l'authentification échoue

-Si vous voulez gérer les erreurs dans Spring, définissez une classe qui hérite ErrorController (une classe fournie par Spring).

ErrorController


import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.annotation.NonAuth;

@Controller
public class ErrController implements ErrorController {

    private static final String PATH = "/error";

    @RequestMapping("/404")
    @NonAuth
    String notFoundError() {
        return "test/error";
    }

    @RequestMapping(PATH)
    @NonAuth
    String home() {
        return "test/error";
    }

    @Override
    @NonAuth
    public String getErrorPath() {
        return PATH;
    }

}

-Comme la méthode définie n'effectue pas de traitement d'authentification, une annotation NonAuth est ajoutée. -Il semble que return false doit être effectué après l'envoi de l'écran d'erreur dans la classe Interceptor. En effet, si vous n'écrivez pas return false, la méthode du gestionnaire (méthode du contrôleur mappé) sera activée même si la transition vers l'écran d'erreur est effectuée. Je me suis référé au site suivant. https://stackoverflow.com/questions/44740332/redirect-using-spring-boot-interceptor Je vais essayer de traduire sur Google ce qui est écrit sur le site ci-dessus.

Returns: true if the execution chain should proceed with the next interceptor or the handler itself. Else, DispatcherServlet assumes that this interceptor has already dealt with the response itself. Vrai si la chaîne d'exécution doit passer à l'intercepteur suivant ou au gestionnaire lui-même. Sinon, DispatcherServlet suppose que cet intercepteur a déjà traité la réponse elle-même.

Je ne suis pas sûr de ce que vous dites dans "Si non ...", mais je pense que DispatcherServlet supposera probablement qu'une réponse a déjà été renvoyée lorsqu'elle est renvoyée avec preHandle (sinon le contrôleur). Puisque la méthode de est démarrée, est-ce que "sinon" signifie "si faux"?). Quoi qu'il en soit, si vous ne voulez pas appeler la méthode du contrôleur, écrivez return false.

Le Handler qui passe à preHandle () n'est pas toujours le HandlerMethod

-Je vérifie si le gestionnaire est un HandlerMethod dans la classe Interceptor, car le gestionnaire n'est pas nécessairement un HandlerMethod. -Par exemple, si vous essayez d'envoyer une demande à une adresse qui n'est pas censée être mappée, ResourceHttpRequestHandler sera transmis. ・ J'ai fait référence au site suivant. https://qiita.com/tukiyo320/items/d51ea698c848414b5874

référence: Configurer l'intercepteur avec springboot Mettre le traitement avant et après la méthode du contrôleur dans Interceptor Pré-traiter la méthode du contrôleur avec une annotation Spring Boot spécifique WebMvcConfigurer Memorandum of Spring Boot 2.0 (Spring 5) Afficher l'écran d'erreur avec Springboot J'étais accro à l'utilisation de Spring Boot (environ 1.2) [Mis à jour de temps en temps] RedirectusingSpringbootinterceptor La méthode qui vient à preHandle n'est pas toujours la HandlerMethod

Recommended Posts

Utilisez Interceptor au printemps
Comment utiliser Lombok au printemps
Utiliser la méthode de requête DynamoDB avec Spring Boot
Inject Logger au printemps
Utilisez java.time avec Jackson
Utiliser le filtre de servlet avec Spring Boot [compatible Spring Boot 1.x, 2.x]
Utiliser OpenCV avec Java
Microservices dans Spring Cloud
Utiliser MouseListener avec le traitement
Utiliser des images avec des rails
Utiliser PostgreSQL dans Scala
[JAVA] [Spring] [MyBatis] Utiliser IN () avec SQL Builder
Obtenez des cookies au printemps
Utiliser PreparedStatement en Java
Comment utiliser CommandLineRunner dans Spring Batch of Spring Boot
[JAVA] [Spring] [MyBatis] Utiliser GROUP BY dans SQL Builder
Comment utiliser le référentiel de jobs en mémoire avec Spring Batch
Définir le paramètre contextuel dans Spring Boot
[spring] Utilisons Spring Data JPA
Multi-projets Spring Boot 2 avec Gradle
Utilisez des variables ruby en javascript.
Spring Boot + Springfox springfox-boot-starter 3.0.0 Utilisation
Erreur de connexion à la base de données Spring
Utiliser Spring JDBC avec Spring Boot
Changements majeurs dans Spring Boot 1.5
NoHttpResponseException dans Spring Boot + WireMock
Utilisez plusieurs cases à cocher dans Rails6!
Étape de boucle avec Spring Batch
Comment appeler et utiliser l'API en Java (Spring Boot)
Utilisez thymeleaf3 avec le parent sans spécifier spring-boot-starter-parent dans Spring Boot
Utilisez @ControllerAdvice, @ExceptionHandler, HandlerExceptionResolver dans Spring Boot pour intercepter les exceptions
Utiliser l'authentification de base avec Spring Boot
Chaîne d'appels depuis la chaîne dans l'intégration Spring
Spring Boot Hello World dans Eclipse
Développement d'applications Spring Boot dans Eclipse
Utiliser le constructeur avec des arguments dans cucumber-picocontainer
Remarques sur l'utilisation de Spring Data JDBC
Environnement Java Spring dans vs Code
J'ai participé au JJUG CCC 2019 Spring
Utilisons Twilio en Java! (Introduction)
[Rails] Utiliser des cookies en mode API
[Java] N'utilisez pas "+" dans append!
Utilisez des clés composites dans Java Maps.
Implémenter reCAPTCHA v3 dans Java / Spring
Utiliser le plugin Findbugs dans Eclipse
Stocker les informations de session dans la base de données avec Spring Session
Comment définir et utiliser un profil avec une configuration basée sur des annotations dans le framework Spring
Comment utiliser InjectorHolder dans OpenAM
Implémenter l'API REST avec Spring Boot
Qu'est-ce que @Autowired dans Spring Boot?
Utiliser DBUnit pour le test Spring Boot
Le traitement des événements est effectué au printemps.
Implémenter l'application Spring Boot dans Gradle
Comment utiliser ModelMapper (Spring boot)
Comment utiliser les classes en Java?
Utiliser la complétion dans Eclipse sur Mac
À partir de Spring Boot 0. Utilisez Spring CLI
Solution de contournement d'adresse déjà utilisée (Windows)
Comment utiliser Thymeleaf avec Spring Boot