Spring Security 使用有效的 JWT 返回 403

2024-03-31

我正在使用 Postman 来测试我在 Spring Boot 2.2.6 中使用 Spring Security 创建的简单 OAuth2 API。我在请求新用户凭据时成功收到 JWT,但当我尝试使用标头中的此令牌访问它们时,我的所有端点都会返回 403 Forbidden 错误。

我的课程如下:

我的服务器安全配置:

@Configuration
@EnableWebSecurity
@Order(1)
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
class ServerSecurityConfiguration(
        @Qualifier("userService")
        private val userDetailsService: UserDetailsService
) : WebSecurityConfigurerAdapter() {
    private val logger: Logger = LoggerFactory.getLogger(ServerSecurityConfiguration::class.java)

    @Bean
    fun authenticationProvider(): DaoAuthenticationProvider {
        val provider = DaoAuthenticationProvider()
        provider.setPasswordEncoder(passwordEncoder())
        provider.setUserDetailsService(userDetailsService)

        return provider
    }

    @Bean
    fun passwordEncoder(): PasswordEncoder {
        return BCryptPasswordEncoder()
    }

    @Bean
    @Throws(Exception::class)
    override fun authenticationManagerBean(): AuthenticationManager {
        return super.authenticationManagerBean()
    }

    @Throws(Exception::class)
    override fun configure(auth: AuthenticationManagerBuilder) {
        auth
            .parentAuthenticationManager(authenticationManagerBean())
            .authenticationProvider(authenticationProvider())
            .userDetailsService(userDetailsService)
            .and()
    }

    @Throws(Exception::class)
    override fun configure(http: HttpSecurity) {
        http
            .cors().and().csrf().disable() // remove for production
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
            .and()
                .authorizeRequests()
                    .antMatchers(
                            "/",
                            "/index.html",
                            "/**/*.js",
                            "/**/*.html",
                            "/**/*.css",
                            "/**/*.woff",
                            "/**/*.woff2",
                            "/**/*.svg",
                            "/**/*.ttf",
                            "/**/*.ico",
                            "/**/*.eot",
                            "/**/assets/*",
                            "/api/login/**",
                            "/oauth/token",
                            "/oauth/authorize"
                    )
                        .permitAll()
                    .antMatchers(HttpMethod.POST, "/api/submissions")
                        .authenticated()
                    .antMatchers(HttpMethod.POST, "/api/users")
                        .hasAuthority(Role.ADMIN.name)
                    .antMatchers(HttpMethod.POST,"/api/**")
                        .hasAuthority(Role.ADMIN.name)
                    .antMatchers(HttpMethod.DELETE, "/api/**")
                        .hasAuthority(Role.ADMIN.name)
                    .antMatchers(HttpMethod.PUT, "/api/**")
                        .hasAnyAuthority(Role.ADMIN.name)
                    .antMatchers(HttpMethod.GET, "/api/**")
                        .authenticated()
                    .anyRequest()
                        .authenticated()
    }
}

我的 OAuth2 配置:

@Configuration
@EnableAuthorizationServer
class OAuth2Configuration(
        @Qualifier("authenticationManagerBean") private val authenticationManager: AuthenticationManager,
        private val passwordEncoder: PasswordEncoder,
        private val userService: UserService,
        private val jwt: JwtProperties
) : AuthorizationServerConfigurerAdapter() {
    private val logger = LoggerFactory.getLogger("OAuth2Configuration")

    @Throws(Exception::class)
    override fun configure(clients: ClientDetailsServiceConfigurer?) {
        clients
            ?.inMemory()
            ?.withClient(jwt.clientId)
            ?.secret(passwordEncoder.encode(jwt.clientSecret))
            ?.accessTokenValiditySeconds(jwt.accessTokenValiditySeconds)
            ?.refreshTokenValiditySeconds(jwt.refreshTokenValiditySeconds)
            ?.authorizedGrantTypes(*jwt.authorizedGrantTypes)
            ?.scopes("read", "write")
            ?.resourceIds("api")
    }

    override fun configure(endpoints: AuthorizationServerEndpointsConfigurer?) {
        endpoints
            ?.tokenStore(tokenStore())
            ?.accessTokenConverter(accessTokenConverter())
            ?.userDetailsService(userService)
            ?.authenticationManager(authenticationManager)
    }

    @Bean
    fun accessTokenConverter(): JwtAccessTokenConverter {
        val converter = JwtAccessTokenConverter()
        converter.setSigningKey(jwt.signingKey)

        return converter
    }

    @Bean
    @Primary
    fun tokenServices(): DefaultTokenServices {
        val services = DefaultTokenServices()
        services.setTokenStore(tokenStore())

        return services
    }

    @Bean
    fun tokenStore(): JwtTokenStore {
        return JwtTokenStore(accessTokenConverter())
    }
}

我的资源服务器配置:

@Configuration
@EnableResourceServer
class ResourceServerConfiguration : ResourceServerConfigurerAdapter() {
    override fun configure(resources: ResourceServerSecurityConfigurer?) {
        resources?.resourceId("api")
    }
}

我的用户详细信息服务:

@Service
class UserService(private val repository: UserRepository) : UserDetailsService {
    private val logger: Logger = LoggerFactory.getLogger(UserService::class.java)

    override fun loadUserByUsername(username: String?): UserDetails {
        val user = repository.findByUsername(username)
                ?: throw UserNotFoundException("User with username $username not found.")

        return org.springframework.security.core.userdetails.User
            .withUsername(user.name)
            .password(user.passwordHash)
            .authorities(user.role.name)
            .build()
    }
}

任何帮助将不胜感激,我在这里不知所措。


调试日志如下:

2020-04-21 08:05:42.583 DEBUG 14388 --- [nio-8080-exec-3] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/api/submissions'; against '/api/**'
2020-04-21 08:05:42.583 DEBUG 14388 --- [nio-8080-exec-3] o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /api/submissions; Attributes: [authenticated]
2020-04-21 08:05:42.584 DEBUG 14388 --- [nio-8080-exec-3] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@ac165fba: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2020-04-21 08:05:42.584 DEBUG 14388 --- [nio-8080-exec-3] o.s.s.access.vote.AffirmativeBased       : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@1097cbf1, returned: -1
2020-04-21 08:05:42.601 DEBUG 14388 --- [nio-8080-exec-3] o.s.s.w.a.ExceptionTranslationFilter     : Access is denied (user is anonymous); redirecting to authentication entry point

org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:123) ~[spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) ~[spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118) ~[spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92) [spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) [spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) [spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) [spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) [spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) [spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1594) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.33.jar:9.0.33]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]

看起来我的用户对象没有获得 ADMIN 角色。


更新: 我添加了一个过滤器并打印出了不记名令牌。它确实存在。


有点晚了,但更简单的解决方案可能是创建自定义 Jwt 身份验证转换器:

class CustomJwtAuthenticationConverter : Converter<Jwt, AbstractAuthenticationToken> {

  private val jwtGrantedAuthoritiesConverter = JwtGrantedAuthoritiesConverter()

  override fun convert(source: Jwt): AbstractAuthenticationToken {
    val scopes = jwtGrantedAuthoritiesConverter.convert(source)
    val authorities = source.getClaimAsStringList("authorities")?.map { SimpleGrantedAuthority(it) }
    return JwtAuthenticationToken(source, scopes.orEmpty() + authorities.orEmpty())
  }
}

然后将转换器提供给您的override fun configure(http: HttpSecurity)实施,如​​:

.jwtAuthenticationConverter(CustomJwtAuthenticationConverter())

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Security 使用有效的 JWT 返回 403 的相关文章

随机推荐

  • 通过从客户区的一部分拖动无框窗口来移动它

    正如标题所示 我想仅当用户将窗口从客户区域的一部分拖动时才移动窗口 这将是对正常标题栏移动的模仿 这是因为我的表单是自定义的 并且没有任何标题或标题栏 目前 我使用的代码如下 case WM NCHITTEST return HTCAPTI
  • 你能用 Java 获得基本的 GC 统计数据吗?

    我想让一些长时间运行的服务器应用程序定期输出 Java 中的一般 GC 性能数据 例如 Runtime freeMemory 的 GC 等价物 例如完成的周期数 平均时间等 我们的系统在客户机器上运行 怀疑配置错误的内存池导致了过多的 GC
  • 仅旋转特定 Excel 行中的文本

    我想使用以下命令旋转 Excel 文件中的标题Microsoft Office Interop 为了实现这一目标 我使用以下代码 worksheet Range A1 worksheet UsedRange Columns Count 1
  • HTTP 标头中什么被视为空白

    我刚刚阅读了 HTTP 标准 拟议标准更准确地说 第 1 部分 并对第 3 节倒数第二段中他们认为的 空白 感到困惑 https www rfc editor org rfc rfc7230 section 3 https www rfc
  • 在 Visual Studio 2008 for .NET CF 中处理不同分辨率

    我正在开发一个基于 NET CF 的图形应用程序 我的项目涉及大量绘图图像 我们决定在不同的手机分辨率上移植该应用程序 240 X 240 480 X 640 等 我将如何在单个解决方案 项目中实现这一目标 是否需要根据决议创建不同的项目
  • R 错误:java.lang.OutOfMemoryError:Java 堆空间

    我正在尝试将 R 连接到 Teradata 以将数据直接提取到 R 中进行分析 但是 我收到错误 Error in jcall rp I fetch stride block java lang OutOfMemoryError Java
  • SIP:错误数据连接丢失

    我已经在 android 中使用本机 sip 创建了 sip 应用程序 在其中 我在从 sip 服务器取消注册帐户时遇到问题 每次我得到数据连接丢失我也在android文档中看到 但没有对此错误的简短解释 而且它在注册时面临各种错误 如in
  • AutoMapper 排除字段

    我正在尝试将一个对象映射到另一个对象 但该对象非常复杂 在开发过程中 我希望能够排除一堆字段并逐一访问它们 或者能够指定仅映射我想要的字段 并在每次测试成功时增加字段 So class string field1 string field2
  • 使用 apache 2.4 设置 git-http-backend

    我试图使用 git http backend 和 apache 2 4 设置一个 git 服务器 我发现这个问题 https stackoverflow com questions 26734933 how to set up git ov
  • 如何制作多表头

    I am trying to make a table with 2 headers merged At the moment i made 2 seperate tables with 2 seperate headers and it
  • 用 ssh 替换 telnet

    我有一些程序使用 Net Telnet 模块连接到多个服务器 现在管理员决定将 Telnet 服务替换为 SSH 保留其他所有内容 例如用户帐户 我查看了 Net SSH2 发现我必须更改大部分程序 您是否知道其他更适合相同替代品的 SSH
  • 将 FrameworkElement 及其 DataContext 保存到图像文件未成功

    我有一个名为 UserControl1 的简单 UserControl 其中包含一个 TextBlock
  • 使用正则表达式从字符串中删除日期

    好的 我有一个字符串 title string 它可能类似于以下任何一个 title string 20 08 12 First Test Event title string First Test event 20 08 12 title
  • 为什么 Python 中字典中的项目顺序会改变? [复制]

    这个问题在这里已经有答案了 我正在尝试从一些教程中学习Python 这是我遇到的一个让我困惑的简单例子 gt gt gt d server mpilgrim database master uid sa pwd secret gt gt g
  • Web Worker 和 Canvas 数据

    我看过很多关于网络工作者的帖子
  • 带按钮控件的 DataGridView - 删除行

    我想要在每行的末尾有一个删除按钮DataGridView通过单击我想从绑定列表中删除所需的行 该绑定列表是我的网格的数据源 但我似乎无法做到这一点 我在产品类中创建了一个按钮对象 并使用唯一的 id 实例化它以从列表中删除该对象 但按钮未显
  • 如何桥接 JavaScript(参差不齐)数组和 std::vector> 对象?

    在 JavaScript 中 我有一个 线 列表 每条线都由不定数量的 点 组成 每个点都有以下形式 x y 所以它是一个 3D 参差不齐的数组 现在我需要在 emscripten 的帮助下将它传递给我的 C 代码 embind https
  • Nuget Push 总是返回 404(未找到)

    我尝试将 nuget 包发布到我的 GitHub Packages 帐户 但在所有情况下我都会遇到 404 错误 我已按照 GitHub 网站上的要求进行操作 nuget source Add Name GitHub Source http
  • 限制异步任务

    我想运行一堆异步任务 并限制在任何给定时间可以等待完成的任务数量 假设您有 1000 个 URL 并且您只想一次打开 50 个请求 但是 一旦一个请求完成 您就会打开与列表中下一个 URL 的连接 这样 每次始终打开 50 个连接 直到 U
  • Spring Security 使用有效的 JWT 返回 403

    我正在使用 Postman 来测试我在 Spring Boot 2 2 6 中使用 Spring Security 创建的简单 OAuth2 API 我在请求新用户凭据时成功收到 JWT 但当我尝试使用标头中的此令牌访问它们时 我的所有端点