用户自定义认证使用
工作原理
- 引入devspore-auth-starter依赖后,会在SDK内自动注册认证Filter:AuthAuthenticationFilter。
- 调用业务接口时会自动执行已注册的认证Filter,AuthAuthenticationFilter.doFilterInternal中将通过SPI方式先调用TokenParser的实现类(DefaultTokenParser,可自定义)完成token解析。
- AuthAuthenticationFilter.doFilterInternal在token解析成功后将解析出的用户信息通过SPI方式调用UserStore的实现类(DefaultUserStore,用户可自定义)存储用户信息供后续业务代码使用。
约束与限制
TokenParser实现类与UserStore实现类,均需注册成bean,并完成bean扫描,确保Spring容器中可获取到对应bean。
TokenParser接口介绍
package com.huaweicloud.devspore.auth.commons.spi; import com.huawei.devspore.plugin.spi.authentication.UserInfo; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; public interface TokenParser { /** * 根据token解析用户信息 * * @param token * @param response * @return 用户信息 UserInfo */ UserInfo parserToken(String token, HttpServletResponse response); /** * 根据HttpRequest解析用户信息 * * @param httpServletRequest * @param response * @return 用户信息 UserInfo */ UserInfo parserToken(HttpServletRequest httpServletRequest, HttpServletResponse response); }
两个方法,用户选其一实现即可;AuthAuthenticationFilter中通过devspore.auth.in-header配置值(默认true,配置说明详见下文“配置说明”章节)自动调用相应方法。
- 若token定义在header中,需实现parserToken(String token, HttpServletResponse response)接口,token获取根据配置由devspore-auth-starter获取。
- 若token未定义在header中,devspore.auth.in-header配置为false,并实现parserToken(HttpServletRequest httpServletRequest, HttpServletResponse response)接口。
UserInfo用户信息类
package com.huawei.devspore.plugin.spi.authentication; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; import java.io.Serializable; import java.util.List; /** * 用户信息 */ @Data public class UserInfo { /** * 用户Id */ private String userId; /** * 用户名 */ private String userName; /** * 租户Id */ private String tenantId; /** * 租户名 */ private String tenantName; /** * 请求token */ private String token; /** * 用户角色 */ private List<String> roles; /** * JWTToken信息,仅JWTToken使用 */ private JwtInfo jwtInfo; @JsonIgnoreProperties(ignoreUnknown = true) @Data public static final class JwtInfo implements Serializable { private static final long serialVersionUID = -2464405170204203810L; /** * 签发者 */ private String iss; /** * 主题 */ private String sub; /** * 签收者 */ private List<String> aud; /** * 过期时间 */ private String exp; /** * 生效时间 */ private String nbf; /** * 签发时间 */ private String iat; /** * Jwt唯一ID */ private String jti; } }
实现TokenParser接口示例
import com.huawei.devspore.plugin.spi.authentication.UserInfo; import com.huaweicloud.devspore.auth.commons.spi.TokenParser; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; @Component public class CustomTokenParser implements TokenParser { /** * 若token定义在header中,可使用该接口,token获取根据配置由devspore-auth获取 * * @param token * @param response * @return UserInfo */ @Override public UserInfo parserToken(String token, HttpServletResponse response) { // 自定义token解析 ...... // 判断token是否过期 ...... UserInfo userInfo = new UserInfo(); // 根据解析后的token信息填充UserInfo对象 ...... return userInfo; } /** * 若token未定义在header中,使用该接口 * * @param request * @param response * @return UserInfo */ @Override public UserInfo parserToken(HttpServletRequest request, HttpServletResponse response) { // 从httpServletRequest获取token ...... // 自定义token解析 ...... // 判断token是否过期 ...... UserInfo userInfo = new UserInfo(); // 根据解析后的token信息填充UserInfo对象 ...... return userInfo; } }
- token解析成功返回用户信息UserInfo,UserInfo中userId为空则默认解析失败。
- token解析失败,返回UserInfo为空,可抛出com.huaweicloud.devspore.auth.commons.exception.DevsporeAuthException,也可使用用户自定义异常。
UserStore接口介绍
package com.huawei.devspore.plugin.spi.authentication; /** * 用户信息接口 */ public interface UserStore { /** * 设置用户信息 * @param userInfo */ void setUserInfo(UserInfo userInfo); /** * 获取用户信息 * @return UserInfo */ UserInfo getUserInfo(); }
- AuthAuthenticationFilter.doFilterInternal会在token解析成功后调用setUserInfo(UserInfo userInfo)接口存储用户信息。
- 后续业务接口鉴权或业务逻辑需要时调用getUserInfo()接口获取当前用户信息。
实现UserStore接口
import com.huawei.devspore.plugin.spi.authentication.UserInfo; import com.huawei.devspore.plugin.spi.authentication.UserStore; import org.springframework.stereotype.Component; @Component public class CustomUserStore implements UserStore { @Override public void setUserInfo(UserInfo userInfo) { // 自定义存储用户信息 ...... } @Override public UserInfo getUserInfo() { UserInfo userInfo = new UserInfo(); // 自定义用户信息获取 ...... return userInfo; } }
认证配置
一般服务配置devspore.auth.exclude-paths与devspore.auth.auth-patterns其中之一即可。
在配置文件中加入devspore相关配置,如下:
devspore: auth: exclude-paths: /healthz;/error;/swagger-ui.html;/swagger-ui/**;/oneaccess-docs/**;/api-docs/**; # 不需要认证的路径,多个规则用;分隔 in-header: true # token是否在header中,默认true token-name: X-Auth-Token # token在header中的参数名,inHeader设置为true时生效,默认X-Auth-Token
devspore: auth: auth-patterns: /v1/** # 需要认证的路径,多个规则用;分隔 in-header: true # token是否在header中,默认true token-name: X-Auth-Token # token在header中的参数名,inHeader设置为true时生效,默认X-Auth-Token
配置说明
参数名 |
是否必须 |
功能 |
---|---|---|
devspore.auth.exclude-paths |
false |
不需要认证的路径,多个规则用“;”分隔,优先级大于devspore.auth.auth-patterns。 |
devspore.auth.auth-patterns |
false |
需要认证的路径,多个规则用“;”分隔。 |
devspore.auth.in-header |
false |
token是否在header中,默认true。 |
devspore.auth.token-name |
false |
token在header中的参数名,inHeader设置为true时生效,默认“X-Auth-Token”。 |