SpringBoot utilizando parámetros de cifrado y descifrado personalizada anotaciones simples notas (+) HandlerMethodArgumentResolver

prefacio

Huang Han de tres y yo volvimos, seis meses antes no actualizar el blog, la experiencia de los últimos seis meses no es fácil,
la cabeza epidemia, yo no practico la empresa a través de gruesos y finos con el personal, una gran cantidad de personas a dejar directamente.
Como pasante, he estado sin piedad expulsado. Por lo que también tiene que volver a prepararse para encontrar un trabajo.
Olvidarse de él, sintiéndolo, había querido emitido ayer, pero ayer estaba claro, el período de luto, se mantiene hasta el día de cabello.

Hombre de pocas palabras, dijo, llegar directamente a la barra. Durante este tiempo yo estaba escribiendo la configuración completa, y la escuela tiene todavía noticias de la escuela, el verdadero techo duro.
Al principio yo sólo quería ser abierto de nuevo a la escuela con seguridad "vejez" Bueno, después de todo, puede encontrar trabajo, pero los amigos y la familia después de la graduación rara vez se cumple.
Así que los padres que deben preocuparse por el pueblo alrededor de Oh.

Debido a que este blog se escribe ahora typora locales anteriores y luego dejar que el blog Park, formato unificado un pequeño
editor de reducción del precio del blog jardín no es muy bueno, esto es un poco dolor de cabeza
hay un punto habilitado formato de código, y se copia a la reducción del precio confundido
lloré, ya en estado de agitación, junto con la edición de la blogosfera en un apretón, Bowen caos ha terminado
después se utilizan archivos de más de rebajas, por lo que la cuestión de lo que el diseño será más paisajismo

En este artículo, el lector será capaz de aprender la siguiente

  • Fácil de usar y anotaciones analíticas
  • HandlerMethodArgumentResolver la parte pertinente del conocimiento

debido

Escribir conjunto completo, esta semana sólo después configurar el fondo, hay un extremo pequeño programa aún no ha comenzado. Como dice el título, el SpringBoot hacer con la acumulación de back-end.
Entonces, por supuesto, se aplica para REST, cuando tengo una URL es / initJson / {id}, cuando pasó directamente sobre el ID de usuario.
Yo quería ser capaz de mirar simplemente el ID de front-end de cifrado, por lo menos no ver ID propaga directamente al back-end. Aunque sólo un juego completo,
pero aún un poco algo al respecto, si elegir para hacer frente a Base64 mejor.
Ahora me gustaría algún parámetro sencillo pasado al extremo frontal, y luego se transmite al extremo posterior con el descifrado de texto cifrado, para evitar transmitir el texto en claro.
Por supuesto, en un entorno real, sin duda utilizar un programa mejor. Aquí sólo estamos diciendo que hay tipo de pensamiento o ese escenario.
Puede iniciar después de dar un ejemplo.

proceso

1. El extremo delantero

Cuando el parámetro de extremo delantero que pasa, cifrado

 // encode是Base64加密的方法,可以自己随便整一个
 data.password = encode(pwd);
 data.username= encode(username);

De esta manera el extremo frontal del texto cifrado se pasa en el pasado.

2. backend

Cuando los parámetros pasados al back-end, que desea resolver la parte posterior del texto cifrado a texto plano, a continuación, el siguiente es el tema de este documento mentiras.
Cuando descifrado, comenzó como un descifrado interfaz dentro.

/**
  *  此时参数接受到的内容是密文
  */
String login(String username, String password) {
       username =  Base64Util.decode(username);
       password=  Base64Util.decode(password);
}

se parece en nada a la derecha, pero en el caso de muchos parámetros, interfaces o más, hacen que desea escribir código cada interfaz por lo que un montón de descifrarlo.
También será la transformación, ¿cómo? Creo que los comentarios, o le gustaría tratar de utilizar las notas, por lo que podría profundizar las notas de estudio.

2.1 Notas

Tomo nota de esta cosa, cuando pensaba que era hora de aprender a la función, el original es que se puede personalizar (grito de la risa).
En este trabajo, se van registrando que sea fácil de entender, si es necesario, puedo actualizar el blog tras un artículo sobre las anotaciones.
O los lectores pueden aprender por su cuenta para averiguar, en este punto, la razón por la que escribo el blog no está en línea, o algo que se encuentra en Internet ahora va a escribir un blog no es el mismo que cuando quiero.
No hacer nada de escritura, por lo que todo lo mismo, por lo que he actualizado el blog no es mucho, básicamente mucho tiempo.
Pero parece que pensar no es correcto, no importa lo que está escrito el contenido del blog, no sólo para facilitar su aprendizaje puede ser conveniente para los demás,
por lo que deben actualizar esperanza frecuencia será mejor.

Volviendo al tema, notas, hay tres cosas principales

  • define de anotación (anotación)
  • Tipo de anotación (ElementType)
  • estrategia de notas (RetentionPolicy)

Echemos un vistazo a la definición de notas, muy simple

// 主要的就是 @interface  使用它定义的类型就是注解了,就跟class定义的类型是类一样。
public @interface Base64DecodeStr {
    /**
     * 这里可以放一些注解需要的东西
     * 像下面这个count()的含义是解密的次数,默认为1次
     */
    int count() default 1;
}

Luego, busquen en los tipos de anotaciones

// 注解类型其实就是注解声明在什么地方
public enum ElementType {
    TYPE,               /* 类、接口(包括注释类型)或枚举声明  */
    FIELD,              /* 字段声明(包括枚举常量)  */
    METHOD,             /* 方法声明  */
    PARAMETER,          /* 参数声明  */
    CONSTRUCTOR,        /* 构造方法声明  */
    LOCAL_VARIABLE,     /* 局部变量声明  */
    ANNOTATION_TYPE,    /* 注释类型声明  */
    PACKAGE             /* 包声明  */
}

// 这个Target就是这么使用的
// 现在这个注解,本人希望它只能声明在方法上还有参数上,别的地方声明就会报错
@Target({ElementType.METHOD, ElementType.PARAMETER})
public @interface Base64DecodeStr {
    int count() default 1;
}

Por último, mira la estrategia de anotaciones

public enum RetentionPolicy {
    SOURCE,  /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了*/
    CLASS,   /* 编译器将Annotation存储于类对应的.class文件中。默认行为  */
    RUNTIME  /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */
}

// 一般用第三个,RUNTIME,这样的话程序运行中也可以使用
@Target({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Base64DecodeStr {
    int count() default 1;
}

Hasta el momento, un comentario sobre la definición del bien. Pero ¿en qué momento hacer el trabajo, entonces tenemos que escribir un análisis sintáctico este comentario.
Entonces pensar en ello, la definición del propósito de este comentario, el parámetro directamente en la interfaz es texto plano, por lo que debe ser puesto de nuevo a los parámetros de texto plano y descifrado de texto cifrado en el interior antes de entrar en la interfaz.
Este paso es que hay alguna buena manera de hacer que esta vez el turno a la siguiente etapa de la protagonista, es HandlerMethodArgumentResolver.

2.2 HandlerMethodArgumentResolver

Sobre el papel de HandlerMethodArgumentResolver y la resolución, por lo que está escrito oficial

/**
 * Strategy interface for resolving method parameters into argument values in
 * the context of a given request.
 * 翻译了一下
 * 策略接口,用于在给定请求的上下文中将方法参数解析为参数值
 * @author Arjen Poutsma
 * @since 3.1
 * @see HandlerMethodReturnValueHandler
 */
public interface HandlerMethodArgumentResolver {

        /**
         * MethodParameter指的是控制器层方法的参数
         * 是否支持此接口
         * ture就会执行下面的方法去解析
         */
	boolean supportsParameter(MethodParameter parameter);

        /**
         * 常见的写法就是把前端的参数经过处理再复制给控制器方法的参数
         */
	@Nullable
	Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
}

Así que esta interfaz, es importante pensar en qué SpringMVC a escribir algunas notas en el controlador, puede recibir los parámetros, se retuvo esta interfaz.
Al igual que @PathVariable común es utilizar esta implementación de la interfaz.

Entiendo que implementan esta interfaz será capaz de acercarse a la parte delantera y la parte trasera de la interfaz entre los parámetros, es sólo para cumplir con los requisitos anteriores.
De hecho, esta interfaz es también parte de una fuente interna SpringMVC común, los lectores aún pueden informarse acerca, la
primavera actual no estoy listo para escribir el código fuente para leer el artículo, porque yo tampoco he visto el sistema de reparto, tal vez más tarde leí en será actualizada sobre el blog.

Continuar, con una interfaz de este tipo se puede utilizar para escribir una resolución de anotación personalizada, los estudiantes atentos se pueden encontrar aquí escribiendo notas de análisis,
a continuación, las notas sólo pueden desempeñar un papel en la capa de control, capa DAO incluso en la capa de servicio es imposible, por lo que si desea utilizar en todo el mundo, entonces
yo creo que se puede cortar con AOP, donde la necesidad de utilizar todo cortado para arriba en él.

HandlerMethodArgumentResolver implementar interfaces a la resolución de escritura.

public class Base64DecodeStrResolver implements HandlerMethodArgumentResolver {

    private static final transient Logger log = LogUtils.getExceptionLogger();

    /**
     * 如果参数上有自定义注解Base64DecodeStr的话就支持解析
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(Base64DecodeStr.class) 
                || parameter.hasMethodAnnotation(Base64DecodeStr.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
         NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        /**
         * 因为这个注解是作用在方法和参数上的,所以要分情况
         */
        int count = parameter.hasMethodAnnotation(Base64DecodeStr.class)
                ? parameter.getMethodAnnotation(Base64DecodeStr.class).count()
                : parameter.getParameterAnnotation(Base64DecodeStr.class).count();
        /**
         * 如果是实体类参数,就把前端传过来的参数构造成一个实体类
         * 在系统中本人把所有实体类都继承了BaseEntity
         */
            if (BaseEntity.class.isAssignableFrom(parameter.getParameterType())) {
                Object obj = parameter.getParameterType().newInstance();
                webRequest.getParameterMap().forEach((k, v) -> {
                    try {
                        BeanUtils.setProperty(obj, k, decodeStr(v[0], count));
                    } catch (Exception e) {
                        log.error("参数解码有误", e);
                    }
                });
                // 这里的return就会把转化过的参数赋给控制器的方法参数
                return obj;
                // 如果是非集合类,就直接解码返回
            } else if (!Iterable.class.isAssignableFrom(parameter.getParameterType())) {
                return decodeStr(webRequest.getParameter(parameter.getParameterName()), count);
            }
        return null;
    }

    /**
     * Base64根据次数恢复明文
     *
     * @param str   Base64加密*次之后的密文
     * @param count *次
     * @return 明文
     */
    public static String decodeStr(String str, int count) {
        for (int i = 0; i < count; i++) {
            str = Base64.decodeStr(str);
        }
        return str;
    }
}

Resolver continuación, registrada lo que esta costumbre.
En este caso no es un perfil registrado

@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
    //region 注册自定义HandlerMethodArgumentResolver
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(base64DecodeStrResolver());
    }

    @Bean
    public Base64DecodeStrResolver base64DecodeStrResolver() {
        return new Base64DecodeStrResolver();
    }
    //endregion
}

Utiliza anotaciones en la capa del controlador.

/**
 * 先试试给方法加注解
 */
@Base64DecodeStr 
public void login(@NotBlank(message = "用户名不能为空")  String username,
                   @NotBlank(message = "密码不能为空") String password) {
            System.out.println(username);
            System.out.println(password);
    }

ver resultados

  • los valores tradicionales distales
  • la recepción de servicios de fondo

En este punto se ha logrado toda la función, nos fijamos en la clave de API

// 这个就是一个参数,控制层的方法参数
MethodParameter parameter
    // 常用方法
    hasMethodAnnotation()  是否有方法注解
    hasParameterAnnotation()  是否有参数注解
    getMethodAnnotation()  获取方法注解(传入Class可以指定)
    getParameterAnnotation() 获取参数注解(传入Class可以指定)
    getParameterType()  获取参数类型


// 这个可以理解为是前端传过来的东西,里面可以拿到前端传过来的密文,也就是初始值,没有被处理过的
NativeWebRequest webRequest
    // 常用方法 其实这几个都是同一个 基于map的操作
    getParameter()  
    getParameterMap()
    getParameterNames()
    getParameterValues()

estudio 2.3 profundidad

El ejemplo anterior es en el proceso de anotación, intente siguiente anotación en parámetros.

/**
 * 注解一个参数
 */
public void login(@NotBlank(message = "用户名不能为空") @Base64DecodeStr  String username,
                   @NotBlank(message = "密码不能为空") String password) {
            System.out.println(username);
            System.out.println(password);
}
/*****************输出******************************/
username
WTBkR2VtTXpaSFpqYlZFOQ==

/**
 * 注解两个参数
 */
public void login(@NotBlank(message = "用户名不能为空") @Base64DecodeStr  String username,
                   @NotBlank(message = "密码不能为空") @Base64DecodeStr String password) {
            System.out.println(username);
            System.out.println(password);
}
/*****************输出******************************/
username
password

Las notas también se pueden ver en el parámetro, y luego mirar de nuevo al mismo tiempo la anotación en el método y los parámetros, piensan al respecto.
Notas sobre el supuesto de que el método preferido, seguido de notas sobre los parámetros, será analizada dos veces,
es decir, el primer texto cifrado en texto llano es anotado método resuelve, entonces analizado de nuevo después de estar parámetro anotación en otra cosa.

/**
 * 注解方法 注解参数
 */
@Base64DecodeStr
public void login(@NotBlank(message = "用户名不能为空") @Base64DecodeStr  String username,
                   @NotBlank(message = "密码不能为空") @Base64DecodeStr String password) {
            System.out.println(username);
            System.out.println(password);
}
/*****************输出******************************/
username
password

la salida de texto sin formato es correcta, que el supuesto anterior no se cumple, vamos a Kankan donde está el problema.

Recordemos que en el momento del análisis, estamos utilizando webRequestel getParameter, y webRequestqué valores son a tomar el relevo de la parte delantera,
de modo decodeStr descifrado se descifra en la parte frontal del valor, por supuesto, devolverá el contenido correcto (texto plano), por lo que incluso notas es un método para descifrar, desencriptar es el valor de la parte delantera,
y luego a las notas de atributos, se descifra el valor de su extremo delantero, la anotación atributo de contenido descifrado no parece que el método anotado para descifrar el contenido a cabo.
Desde este punto de vista, es de hecho tal cosa, incluso si no aparecen las anotaciones y notas parámetro del método, junto con el efecto de descifrado repetido.

Sin embargo, esto es sólo una de las razones, al principio yo no pienso en esto, después haga clic en un punto de interrupción curiosidad de rastrear la fuente.

@Override
@Nullable
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
                 // 获取参数的resolver,参数的定位是控制器.方法.参数位置 ,所以每个parameter都是唯一的
                 // 至于重载的啊,不知道没试过,你们可以试下,XD
		HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
		if (resolver == null) {
		  throw new IllegalArgumentException("Unsupported parameter type [" +
		  parameter.getParameterType().getName() + "]. supportsParameter should be called first.");
		}
		  return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}

@Nullable
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
                // argumentResolverCache是一个缓存,map,
                // 从这里可以看出,每个控制器方法的参数都会被缓存起来,
		HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
		if (result == null) {
			for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
                            // 调用supportsParameter看看是否支持
	                    if (resolver.supportsParameter(parameter)) {
				result = resolver;
                                // 一个参数可以有多个resolver 
	        		this.argumentResolverCache.put(parameter, result);
				break;
				}
			}
		}
		return result;          
}


Así que la pregunta entonces refinarlo, cuando también métodos anotar y parámetros, las llamadas varias veces getArgumentResolver () que,
para facilitar la visualización, anotación que pasará a diferentes parámetros.
Antes de eso, en primer lugar poner un pequeño episodio, se encuentra en la depuración de problemas

/**
 * 注解方法
 */
@Base64DecodeStr( count = 10)
public void login(@NotBlank(message = "用户名不能为空") String username,
                   @NotBlank(message = "密码不能为空")  String password) {
            System.out.println(username);
            System.out.println(password);
}

Ir antes de que el

parámetro es menor que el método de obtención de este anotaciones personalizadas.
Cuando el código para descender, supportsParameter cuando

este tiempo allí, y en silencio.
¿Cuál es la razón por la que no encontré temporal.

Más cerca de casa, seguimos depuración

/**
 * 注解方法 注解全部参数
 */
@Base64DecodeStr( count = 30)
public void login(@NotBlank(message = "用户名不能为空") @Base64DecodeStr(count = 10)  String username,
                   @NotBlank(message = "密码不能为空") @Base64DecodeStr(count =20) String password) {
            System.out.println(username);
            System.out.println(password);
}

O ir a ver la anotación parámetro del método anotada.

  • Primero vienen en

    se puede ver el primer nombre de usuario parámetro
  • La segunda venida

    sigue siendo la primera nombre de usuario parámetro
  • La tercera entró

    para ver el segundo parámetro de contraseña
  • En cuarto lugar llegó

    también el segundo parámetro de contraseña

Así se puede ver, no hay un método para ir anotaciones o método anotado irá dos veces, una vez a la anotación de parámetros, por lo que un total de cuatro veces, lo que no es ningún problema.
Esto es lo que ocurrió. Si no va método anotado, un método que notas cómo se lleva a efecto, he encontrado la razón detrás

  /**
   * 原来是因为这里,虽然不是因为方法注解进来的,但是这里优先取的是方法注解的值,
   * 所以如果想让属性注解优先的话这里改一下就行
   */
  int count = parameter.hasMethodAnnotation(Base64DecodeStr.class)
                ? parameter.getMethodAnnotation(Base64DecodeStr.class).count()
                : parameter.getParameterAnnotation(Base64DecodeStr.class).count();

Así que la verdad está ahí fuera, si las anotaciones de método y notas a los mismos atributos momento adicionar, a continuación, se llevarán a cabo cuatro veces getArgumentResolver (),
que sólo llama supportsParameter dos veces (), porque la segunda vez para tomar el valor de cada parámetro directamente desde el mapa de la ya no ir supportsParameter () a.

final

Hasta ahora hemos completado este viaje, de adelante hacia atrás.
resumir brevemente.

  • comentario
    • Definiciones: @interface
    • 类型: tipo, FIELD, METHOD, el parámetro, constructor, LOCAL_VARIABLE, ANNOTATION_TYPE, PAQUETE
    • Estrategia: FUENTE, clase, DURACIÓN
  • HandlerMethodArgumentResolver
    • Acción: como interceptores, el extremo posterior del extremo frontal para el nivel medio
    • dos métodos
      • supportsParameter: ya sea para apoyar el uso del sistema de resolución
      • resolveArgument: Resolver quiere hacer algo

Entonces comentario en la sección de solución tampoco es perfecta, por ejemplo, si el tipo de parámetro es una colección de palabras debe ser cómo hacer frente a, este es un seguimiento.

En esta parte son los problemas reales que encontré y grabado desde el principio quiere cifrar los parámetros de cifrado para encontrar maneras de lograr esta función,
tal idea, espero para dar nuevas personas un poco de inspiración, por supuesto, también tenemos que seguir aprendiendo propio , o no pueden encontrar trabajo, puedo único equipo conjunto completo bordes ocupado para pasar tiempo revisado.
Un hombre melancólico, cuanto más, oye, no largo aliento, y ahora son los dos puntos de la noche, listo para dormir.

Supongo que te gusta

Origin www.cnblogs.com/yellowgg/p/12635553.html
Recomendado
Clasificación