用户自定义认证使用
工作原理
- 引入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”。 |