Spring Security社交登录POC:配置context-path后仍返回401
我正在做Spring Security社交登录的POC开发,遇到一个问题:调用带context-path的API时返回Http Status 401,我已经在antMatchers("/newcontext/**").permitAll()里加了context-path,但没用。
相关配置与代码
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.3</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example.</groupId> <artifactId>spring-security</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-security</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>
WebSecurityConfig.java
package com.example.springsecurity.config; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.web.authentication.HttpStatusEntryPoint; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests(a -> a .antMatchers("/newcontext/**").permitAll() .antMatchers("/", "/error","/webjars/**").permitAll() .anyRequest().authenticated() ) .exceptionHandling(e -> e .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)) ) .oauth2Login(); } }
TestController.java
package com.example.springsecurity.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @GetMapping("/test") public String test(){ return "success"; } }
application.yml
server: servlet: context-path: /newcontext port: 8081 spring: security: oauth2: client: registration: facebook: clientId: ********* clientSecret: ********* accessTokenUri: https://graph.facebook.com/oauth/access_token userAuthorizationUri: https://www.facebook.com/dialog/oauth tokenName: oauth_token authenticationScheme: query clientAuthenticationScheme: form resource: userInfoUri: https://graph.facebook.com/me
请求与响应
GET http://localhost:8081/newcontext/test
响应:401 Unauthorized
我试过调整/newcontext/**在antMatchers中的顺序,也试过把它和其他允许路径放在一起:
.antMatchers("/", "/error","/webjars/**", "/newcontext/**").permitAll()
但问题依旧。
问题原因与解决方法
核心问题是:Spring Security的路径匹配是基于servlet路径(去掉context-path后的路径),不是完整的请求路径。
你在application.yml里配置了context-path: /newcontext,所以当请求http://localhost:8081/newcontext/test时,Spring Security看到的实际路径是/test,而不是/newcontext/test。你之前在antMatchers里写/newcontext/**,根本匹配不到实际的请求路径,所以会触发认证拦截返回401。
正确的配置方式
修改WebSecurityConfig中的路径匹配规则,去掉context-path,直接写控制器对应的路径:
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests(a -> a .antMatchers("/test").permitAll() // 直接匹配控制器的路径 .antMatchers("/", "/error","/webjars/**").permitAll() .anyRequest().authenticated() ) .exceptionHandling(e -> e .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)) ) .oauth2Login(); }
如果要允许context-path下的所有请求,直接写/**即可:
.antMatchers("/**").permitAll()
这样配置后,所有发往/newcontext下的请求都会被允许访问,不需要在规则里带上context-path。
内容的提问来源于stack exchange,提问作者anonymous

