springCloud+gateway实现token验证

拦截器实现gateway中得全局拦截器GlobalFilter, Ordered
验证思路:
1.获取请求路径path,判断是否为忽略文件
2.如不是获取token,解析出userId,获取角色列表 然后角色列表中获取菜单路径(请求页面)
3菜单路径与path进行比对如相同就通过,负责无权限
TokenFilter:

package com.cuslink.gateway.filters;


import com.cuslink.common.constants.StatusCode;
import com.cuslink.common.constants.SysConstants;
import com.cuslink.common.util.JsonUtils;
import com.cuslink.common.util.JwtUtils;
import com.cuslink.gateway.entity.TblMenu;
import com.cuslink.gateway.entity.TblRoleMenu;
import com.cuslink.gateway.entity.TblUserRole;
import com.cuslink.gateway.mapper.TblMenuMapper;
import com.cuslink.gateway.mapper.TblRoleMenuMapper;
import com.cuslink.gateway.mapper.TblUserRoleMapper;
import com.cuslink.service.AjaxResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;


/**
 * @author 
 */
@Component
@Slf4j
public class TokenFilter implements GlobalFilter, Ordered {

    @Autowired
    private TblUserRoleMapper userRoleMapper;
    @Autowired
    private TblRoleMenuMapper roleMenuMapper;
    @Autowired
    private TblMenuMapper menuMapper;


    /**
     * 忽略过滤的路径
     */

    @Value("${com.cuslink.ignoreAuthUrls}")
    private String ignoreAuthUrls;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        // 获取当前请求路径
        String path = request.getURI().getPath();
        log.info("当前路径为" + path + ",判断是否为忽略路径.");
        // 查询是否是忽略路径
        boolean b = decideIgnore(path);
        if (b) {
            // 忽略路径直接放行
            log.info("当前路径为" + path + ",是忽略过滤路径,直接放行!");
            return chain.filter(exchange);
        } else {
            log.info("当前路径为" + path + ",不是忽略过滤路径,开始校验!");
            // 获取当前请求中的token
            String token = request.getHeaders().getFirst(SysConstants.ACCESS_TOKEN);
            if (!StringUtils.isEmpty(token)) {
                // 查询是否有该路径的权限
                String userId = JwtUtils.getUserId(token);
                if (!StringUtils.isEmpty(userId)) {
                    log.info("当前用户ID为:"+userId);
                    // 根据用户ID获取角色列表
                    List<TblUserRole> list = userRoleMapper.findRoleByuserID(userId);
                    if (!CollectionUtils.isEmpty(list)) {
                        // 根据角色ID获取角色菜单关联列表
                        List<TblRoleMenu> menuIds = roleMenuMapper.findMenuByRoleID(list);
                        if (!CollectionUtils.isEmpty(menuIds)) {
                            // 根据每一个菜单获取路径进行匹配
                            List<TblMenu> menuPaths = menuMapper.findMenusByMenuID(menuIds);
                            if (!CollectionUtils.isEmpty(menuPaths)) {
                                for (TblMenu menuPath : menuPaths) {
                                    if (menuPath.getFullPath().equals(path)) {
                                        log.info("用户ID为" + userId + "正在访问,当前路径为" + path + ",校验通过!");
                                        // 放行
                                        return chain.filter(exchange);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        // 返回无权访问信息
        log.info("当前路径为" + path + ",校验失败!当前用户ID没有权限访问!");
        //拦截,提示未授权错误
        DataBuffer buffer = setResponseInfo(response, AjaxResult.getAjaxResult(StatusCode.ACCESS_NO_AUTH));
        return response.writeWith(Mono.just(buffer));
    }


    private DataBuffer setResponseInfo(ServerHttpResponse response, Object object) {
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        byte[] responseByte = JsonUtils.objToString(object).getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(responseByte);
        return buffer;
    }

    /**
     * 判断是否是忽略路径
     *
     * @param servletPath
     * @return
     */
    private boolean decideIgnore(String servletPath) {
        //跳过不需要验证的路径
        String[] ignoreUrl = this.ignoreAuthUrls.split(",");
        for (String ignore : ignoreUrl) {
            if (ignore.equals(servletPath) || ignore.endsWith("**") && servletPath.contains(ignore.substring(0, ignore.length() - 2))) {
                return true;
            }
        }
        return false;
    }

    @Override
    public int getOrder() {
        return -100;
    }
}

application.properties:

com.login-center.Url=/cas/login/getRightsByKey1
com.cuslink.ignoreUrls=/user/v1/authen/loginForPortal,/user/v1/authen/registerForPortal,\
  /portal/v1/healthCenter/findAllHealthCenter,/portal/v1/healthCenter/findHealthCenterDetail,\
  /portal/v1/situation/getSituationList,\
  /portal/v1/tag/list,\
  /portal/v1/param/**,\
  /portal/v1/article/pageList,/portal/v1/article/detail,/portal/v1/article/findHotArticle,\
  /portal/v1/column/findIndexColumn,/portal/v1/column/findColumnByPid,\
  /health-management/v2/api-docs,\
  /health-user/v2/api-docs,\
  /health-portal/v2/api-docs,\
  /health-consult/v2/api-docs,\
  /health-business/v2/api-docs,\
  /health-mobile/v2/api-docs,/health-user/v1/authen/loginForPortal,/health-user/v1/authen/registerForPortal,
com.cuslink.ignoreAuthUrls=/portal/v1/healthCenter/findAllHealthCenter,

用户角色表:

package com.cuslink.gateway.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * <p>
 * 用户角色表
 * </p>
 *
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("TBL_USER_ROLE")
@ApiModel(value="TblUserRole对象", description="用户角色表")
public class TblUserRole implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "ID",type = IdType.UUID)
    private String id;

    @ApiModelProperty(value = "用户ID")
    @TableField("USER_ID")
    private String userId;

    @ApiModelProperty(value = "角色ID")
    @TableField("ROLE_ID")
    private String roleId;

    @ApiModelProperty(value = "创建时间")
    @TableField("CREATE_TIME")
    private LocalDateTime createTime;

    @ApiModelProperty(value = "更新时间")
    @TableField("UPDATE_TIME")
    private LocalDateTime updateTime;

    @ApiModelProperty(value = "创建人")
    @TableField("CREATE_ID")
    private String createId;

    @ApiModelProperty(value = "更新人")
    @TableField("UPDATE_ID")
    private String updateId;

    @ApiModelProperty(value = "是否删除,0不删除,1删除")
    @TableField("DELETE_FLAG")
    private Integer deleteFlag;


}

菜单表:

package com.cuslink.gateway.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 菜单表
 * </p>
 *
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("TBL_MENU")
@ApiModel(value="TblMenu对象", description="菜单表")
public class TblMenu implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "ID",type = IdType.UUID)
    @NotBlank(message = "ID不能为空!")
    private String id;

    @ApiModelProperty(value = "名称")
    @TableField("MENU_NAME")
    private String menuName;

    @ApiModelProperty(value = "描述")
    @TableField("DESCRIPTION")
    private String description;

    @ApiModelProperty(value = "英文码")
    @TableField("CODE")
    private String code;

    @ApiModelProperty(value = "父菜单ID")
    @TableField("PID")
    private String pid;

    @ApiModelProperty(value = "图标")
    @TableField("ICON")
    private String icon;

    @ApiModelProperty(value = "序号")
    @TableField("SORT_NUM")
    private Integer sortNum;

    @ApiModelProperty(value = "全路径")
    @TableField("FULL_PATH")
    private String fullPath;

    @ApiModelProperty(value = "创建时间")
    @TableField("CREATE_TIME")
    private LocalDateTime createTime;

    @ApiModelProperty(value = "更新时间")
    @TableField("UPDATE_TIME")
    private LocalDateTime updateTime;

    @ApiModelProperty(value = "创建人")
    @TableField("CREATE_ID")
    private String createId;

    @ApiModelProperty(value = "更新人")
    @TableField("UPDATE_ID")
    private String updateId;

    @ApiModelProperty(value = "是否删除,0不删除,1删除")
    @TableField("DELETE_FLAG")
    private Integer deleteFlag;

    @TableField(exist = false)
    private List<TblMenu> children;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值