需求
对于需要授权或登录
的系统,大量的接口,需要获取到用户的 授权信息 / 登录信息
。这些信息可能存在于Session或token中。
将授权信息 / 登录信息
解析为接口
的参数
。
这样避免了在每个接口中重复写信息解析的代码,提交了效率。
实现方式
- 注解:@Authorization
- 授权信息实体:Auth
- 参数解析器:HandlerMethodArgumentResolver
- 配置: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);
}
}
效果
登录接口保存了授权信息;在其他接口,在已登录的前提下,能够从接口方法的参数中获得授权信息对象。
先调用登录接口,再调用修改密码接口,打印日志如下: