SaToken 鉴权

@SaCheckPermission

StpLogic#checkPermissionAnd

public void checkPermissionAnd(String... permissionArray) {
        Object loginId = this.getLoginId();
        List<String> permissionList = this.getPermissionList(loginId);
        String[] var4 = permissionArray;
        int var5 = permissionArray.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            String permission = var4[var6];
            if (!this.hasElement(permissionList, permission)) {
                throw (new NotPermissionException(permission, this.loginType)).setCode(11051);
            }
        }

    }
    
public void checkPermissionOr(String... permissionArray) {
        Object loginId = this.getLoginId();
        List<String> permissionList = this.getPermissionList(loginId);
        String[] var4 = permissionArray;
        int var5 = permissionArray.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            String permission = var4[var6];
            if (this.hasElement(permissionList, permission)) {
                return;
            }
        }

        if (permissionArray.length > 0) {
            throw (new NotPermissionException(permissionArray[0], this.loginType)).setCode(11051);
        }
    }

StpInterface#getPermissionList()获取权限列表

  List<String> getPermissionList(Object var1, String var2);

在线用户src/main/java/com/ruoyi/auth/listener/UserActionListener.java

/**
     * 每次登录时触发
     */
    @Override
    public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
        UserType userType = UserType.getUserType(loginId.toString());
        if (userType == UserType.SYS_USER) {
            UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
            String ip = ServletUtils.getClientIP();
            LoginUser user = LoginHelper.getLoginUser();
            SysUserOnline userOnline = new SysUserOnline();
            userOnline.setIpaddr(ip);
            userOnline.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
            userOnline.setBrowser(userAgent.getBrowser().getName());
            userOnline.setOs(userAgent.getOs().getName());
            userOnline.setLoginTime(System.currentTimeMillis());
            userOnline.setTokenId(tokenValue);
            userOnline.setUserName(user.getUsername());
            if (ObjectUtil.isNotNull(user.getDeptName())) {
                userOnline.setDeptName(user.getDeptName());
            }
            if(tokenConfig.getTimeout() == -1) {
                RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, userOnline);
            } else {
                RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, userOnline, Duration.ofSeconds(tokenConfig.getTimeout()));
            }
            log.info("user doLogin, useId:{}, token:{}", loginId, tokenValue);
        } else if (userType == UserType.APP_USER) {
            // app端 自行根据业务编写
        }
    }

全局过滤,白名单操作

src/main/java/com/ruoyi/gateway/filter/AuthFilter.java#getSaReactorFilter

@Configuration
public class AuthFilter {

    /**
     * 注册 Sa-Token 全局过滤器
     */
    @Bean
    public SaReactorFilter getSaReactorFilter(IgnoreWhiteProperties ignoreWhite) {
        return new SaReactorFilter()
            // 拦截地址
            .addInclude("/**")
            .addExclude("/favicon.ico", "/actuator/**")
            // 鉴权方法:每次访问进入
            .setAuth(obj -> {
                // 登录校验 -- 拦截所有路由
                SaRouter.match("/**")
                    .notMatch(ignoreWhite.getWhites())
                    .check(r -> {
                        // 检查是否登录 是否有token
                        StpUtil.checkLogin();

                        // 有效率影响 用于临时测试
                        // if (log.isDebugEnabled()) {
                        //     log.debug("剩余有效时间: {}", StpUtil.getTokenTimeout());
                        //     log.debug("临时有效时间: {}", StpUtil.getTokenActivityTimeout());
                        // }
                    });
            }).setError(e -> SaResult.error("认证失败,无法访问系统资源").setCode(HttpStatus.UNAUTHORIZED));
    }
}

配置白名单src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java

@Data
@NoArgsConstructor
@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "security.ignore")
public class IgnoreWhiteProperties {
    /**
     * 放行白名单配置,网关不校验此处的白名单
     */
    private List<String> whites = new ArrayList<>();

}

内网鉴权src/main/java/com/ruoyi/gateway/filter/ForwardAuthFilter.java

/**
 * 转发认证过滤器(内部服务外网隔离)
 *
 * @author Lion Li
 */
@Component
public class ForwardAuthFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest newRequest = exchange
            .getRequest()
            .mutate()
            // 为请求追加 Same-Token 参数
            .header(SaSameUtil.SAME_TOKEN, SaSameUtil.getToken())
            .build();
        ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
        return chain.filter(newExchange);
    }

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

安全校验依赖项

   <!-- RuoYi Common Security -->
    <dependency>
        <groupId>com.ruoyi</groupId>
        <artifactId>ruoyi-common-security</artifactId>
    </dependency>

src/main/java/com/ruoyi/common/security/config/SecurityConfiguration.java#getSaServletFilter()

 /**
     * 校验是否从网关转发
     */
    @Bean
    public SaServletFilter getSaServletFilter() {
        return new SaServletFilter()
            .addInclude("/**")
            .addExclude("/actuator/**")//排除了健康检测的监控
            .setAuth(obj -> SaSameUtil.checkCurrentRequestToken())
            .setError(e -> SaResult.error("认证失败,无法访问系统资源").setCode(HttpStatus.UNAUTHORIZED));
    }

管理员拥有所有权限src/main/java/com/ruoyi/system/service/impl/SysPermissionServiceImpl.java#getMenuPermission()

    /**
     * 获取菜单数据权限
     *
     * @param user 用户
     * @return 菜单权限信息
     */
    @Override
    public Set<String> getMenuPermission(SysUser user) {
        Set<String> perms = new HashSet<String>();
        // 管理员拥有所有权限
        if (LoginHelper.isAdmin(user.getUserId())) {
            perms.add("*:*:*");
        } else {
            perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
        }
        return perms;
    }
}

src/main/java/com/ruoyi/system/dubbo/RemoteUserServiceImpl.java

    @Override
    public LoginUser getUserInfo(String username) throws UserException {
        SysUser sysUser = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .select(SysUser::getUserName, SysUser::getStatus)
                .eq(SysUser::getUserName, username));
        if (ObjectUtil.isNull(sysUser)) {
            throw new UserException("user.not.exists", username);
        }
        if (UserStatus.DISABLE.getCode().equals(sysUser.getStatus())) {
            throw new UserException("user.blocked", username);
        }
        // 此处可根据登录用户的数据不同 自行创建 loginUser
        return buildLoginUser(userMapper.selectUserByUserName(username));
    }
    
     /**
     * 构建登录用户
     */
    private LoginUser buildLoginUser(SysUser user) {
        LoginUser loginUser = new LoginUser();
        loginUser.setUserId(user.getUserId());
        loginUser.setDeptId(user.getDeptId());
        loginUser.setUsername(user.getUserName());
        loginUser.setPassword(user.getPassword());
        loginUser.setUserType(user.getUserType());
        loginUser.setMenuPermission(permissionService.getMenuPermission(user));
        loginUser.setRolePermission(permissionService.getRolePermission(user));
        loginUser.setDeptName(ObjectUtil.isNull(user.getDept()) ? "" : user.getDept().getDeptName());
        List<RoleDTO> roles = BeanUtil.copyToList(user.getRoles(), RoleDTO.class);
        loginUser.setRoles(roles);
        return loginUser;
    }
Logo

快速构建 Web 应用程序

更多推荐