Spring框架中为指定请求添加Authorization Token请求头
Hey there! Great job getting the token generation set up for your social media API—you’re already making solid progress on securing it. To answer your core question: yes, totally feasible to require an Authorization Header for specific endpoints while leaving others (like login/signup) open. Let’s break down how to implement this cleanly in Spring, whether you want to use Spring Security’s built-in tools or your custom validation function.
If you haven’t already, include the Spring Security starter in your project. This gives you all the tools to handle authentication rules and filters.
For Maven, add this to your pom.xml:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
For Gradle, add this to your build.gradle:
implementation 'org.springframework.boot:spring-boot-starter-security'
Create a security configuration class to define which endpoints are public (no auth needed) and which require a valid token. Here’s how to do it with modern Spring Security (using SecurityFilterChain instead of the old WebSecurityConfigurerAdapter):
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http // Disable CSRF since we're building an API (not a web app with form submissions) .csrf().disable() // Define authorization rules .authorizeHttpRequests(auth -> auth // Allow everyone to access login/register endpoints .antMatchers("/api/auth/login", "/api/auth/register").permitAll() // Require authentication for search endpoints .antMatchers("/api/search/**").authenticated() // Optional: Require auth for all other endpoints (adjust based on your needs) .anyRequest().authenticated() ); return http.build(); } }
Since you already have token generation working, you’ll need a way to validate those tokens on protected endpoints. The cleanest way is to create a custom filter that runs before Spring Security’s default filters. This filter will check for the Authorization Header, validate the token, and set the user’s authentication status if the token is valid.
Here’s a sample filter:
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; public class TokenValidationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // Extract the Authorization header from the request String authHeader = request.getHeader("Authorization"); String requestPath = request.getRequestURI(); // Skip validation for public endpoints (login/register) if (requestPath.startsWith("/api/auth/login") || requestPath.startsWith("/api/auth/register")) { filterChain.doFilter(request, response); return; } // Validate the header format (should be "Bearer <token>") if (authHeader == null || !authHeader.startsWith("Bearer ")) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Missing or invalid Authorization header"); return; } // Extract the token from the header String token = authHeader.substring(7); // Remove "Bearer " prefix // Run your custom token validation logic if (!isValidToken(token)) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid or expired token"); return; } // If token is valid, set the user's authentication in Spring's security context // Replace getUsernameFromToken with your method to extract user info from the token String username = getUsernameFromToken(token); UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken( username, null, new ArrayList<>() // Add roles/permissions here if you need them ); SecurityContextHolder.getContext().setAuthentication(authToken); // Continue processing the request filterChain.doFilter(request, response); } // Your custom token validation method (replace with your actual logic) private boolean isValidToken(String token) { // Example checks: // 1. Verify the token's signature (if using JWT) // 2. Check if the token is not expired // 3. Confirm the token exists in your database (if you're storing active tokens) return true; // Replace with real validation logic } // Your method to extract the username (or user ID) from the token private String getUsernameFromToken(String token) { // Example: Parse the token's claims to get the username return "user123"; // Replace with real extraction logic } }
Then, add this filter to your SecurityConfig so it runs before Spring’s default authentication filter:
@Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf().disable() // Add your custom token filter before the default username/password filter .addFilterBefore(tokenValidationFilter(), UsernamePasswordAuthenticationFilter.class) .authorizeHttpRequests(auth -> auth .antMatchers("/api/auth/login", "/api/auth/register").permitAll() .antMatchers("/api/search/**").authenticated() .anyRequest().authenticated() ); return http.build(); } @Bean public TokenValidationFilter tokenValidationFilter() { return new TokenValidationFilter(); } }
- Public endpoints: Send a POST to
/api/auth/loginor/api/auth/registerwithout an Authorization Header—this should work and return your token. - Protected endpoints: Send a request to
/api/searchwithAuthorization: Bearer <your-generated-token>in the headers. If the token is valid, you’ll get a normal response. If not, you’ll get a 401 Unauthorized error.
- If you’re using JWT tokens, consider using a library like JJWT to simplify token generation and validation (instead of writing all the crypto logic yourself).
- Store tokens securely: For frontend clients, prefer HttpOnly cookies over localStorage to reduce XSS risks (though Bearer tokens are standard for API-only setups).
- Add role-based access control later: If you need to restrict certain endpoints to admins, you can add roles to the
UsernamePasswordAuthenticationTokenand use.hasRole("ADMIN")in your security rules.
内容的提问来源于stack exchange,提问作者K. Janjuha

