授权信息(登录信息)解析为接口方法的参数(@Authorization + HandlerMethodArgumentResolver + WebMvcConfigurer)

需求

对于需要授权或登录的系统,大量的接口,需要获取到用户的 授权信息 / 登录信息 。这些信息可能存在于Session或token中。

授权信息 / 登录信息解析为接口参数

这样避免了在每个接口中重复写信息解析的代码,提交了效率。

在这里插入图片描述

实现方式

  1. 注解:@Authorization
  2. 授权信息实体:Auth
  3. 参数解析器:HandlerMethodArgumentResolver
  4. 配置:WebMvcConfigurer

@Authorization:标记接口中的授权信息参数,用于确定要解析的接口参数;
授权信息实体:用来存储授权信息;
参数解析器:用来实现解析逻辑;
配置:将参数解析器,配置到Spring中。

核心代码

@Authorization

package com.example.core.authorization;

import java.lang.annotation.*;

/**
 * 授权信息-标记注解
 */
@Documented
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Authorization {
    
    
}

Auth:授权信息实体

package com.example.core.authorization;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

@Data
@Schema(name = "授权信息")
public class Auth {
    
    

    @Schema(description = "登录ID", example = "1234567890123456789")
    private String loginId;

    @Schema(description = "登录账号", example = "1001")
    private String account;

}

HandlerMethodArgumentResolver

package com.example.core.authorization;

import com.example.core.authorization.constant.AuthConstant;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

/**
 * 授权信息参数解析器
 */
public class AuthorizationHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
    
    

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
    
    
        return parameter.hasParameterAnnotation(Authorization.class) && parameter.getParameterType() == Auth.class;
    }


    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
    
    
        return webRequest.getAttribute(AuthConstant.AUTHORIZATION, RequestAttributes.SCOPE_SESSION);
    }

}

WebMvcConfigurer

package com.example.core.config;

import com.example.core.authorization.AuthorizationHandlerMethodArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * WebMvc配置器
 */
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
    
    

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    
    
        resolvers.add(new AuthorizationHandlerMethodArgumentResolver());
    }

}

补充代码

授权信息常量

package com.example.core.authorization.constant;

/**
 * 授权信息常量
 */
public class AuthConstant {
    
    

    /**
     * 授权信息 - Session.Attribute 的 name
     */
    public static final String AUTHORIZATION = "authorization";

}

测试

package com.example.web.account.controller;

import com.example.core.authorization.Auth;
import com.example.core.authorization.Authorization;
import com.example.core.authorization.constant.AuthConstant;
import com.example.web.account.model.ChangePasswordParam;
import com.example.web.account.model.LoginParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

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

@Slf4j
@RestController
@RequestMapping("accounts")
@Tag(name = "账号")
public class AccountController {
    
    

    @PostMapping("login")
    @Operation(summary = "登录")
    public void login(@Valid @RequestBody LoginParam param, HttpServletRequest request) {
    
    
        log.info("登录:LoginParam={}", param);

        Auth auth = new Auth();
        auth.setLoginId("1234567890123456789");
        auth.setAccount(param.getAccount());

        // 登录成功,记录用户的授权状态
        HttpSession session = request.getSession();
        session.setAttribute(AuthConstant.AUTHORIZATION, auth);
    }


    @PutMapping("change_password")
    @Operation(summary = "修改密码")
    @Parameter(name = "auth", hidden = true)
    public void changePassword(@Authorization Auth auth,
                               @Valid @RequestBody ChangePasswordParam param,
                               HttpServletRequest request) {
    
    
        log.info("修改密码:Authorization={}", auth);
        log.info("修改密码:ChangePasswordParam={}", param);
    }

}

效果

登录接口保存了授权信息;在其他接口,在已登录的前提下,能够从接口方法的参数中获得授权信息对象。

先调用登录接口,再调用修改密码接口,打印日志如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/sgx1825192/article/details/134058137