更新时间:2025-01-09 GMT+08:00
分享

用户自定义认证使用

工作原理

  • 引入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相关配置,如下:

示例1:/healthz;/error;/swagger-ui.html;/swagger-ui/**;/oneaccess-docs/**;/api-docs/**;等API无需认证,除此之外所有API均进行认证。
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
示例2:以“/v1/”开头的所有API均进行认证。
devspore:
  auth:
    auth-patterns: /v1/**  # 需要认证的路径,多个规则用;分隔
    in-header: true  # token是否在header中,默认true
    token-name: X-Auth-Token  # token在header中的参数名,inHeader设置为true时生效,默认X-Auth-Token

配置说明

表1 配置说明

参数名

是否必须

功能

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”。

相关文档