package com.tourguide.config;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.tourguide.common.api.ApiResponse;
|
import com.tourguide.security.JwtAuthenticationFilter;
|
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Configuration;
|
import org.springframework.http.HttpMethod;
|
import org.springframework.http.MediaType;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfigurationSource;
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
|
import java.nio.charset.StandardCharsets;
|
import java.util.Arrays;
|
import java.util.Collections;
|
|
@Configuration
|
public class SecurityConfig {
|
@Bean
|
public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
|
|
@Bean
|
public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtAuthenticationFilter jwtFilter, ObjectMapper objectMapper)
|
throws Exception {
|
http.csrf().disable()
|
.cors().and()
|
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
.exceptionHandling()
|
.authenticationEntryPoint((request, response, exception) -> {
|
response.setStatus(401);
|
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
objectMapper.writeValue(response.getWriter(), ApiResponse.failure(401, "请先登录"));
|
})
|
.accessDeniedHandler((request, response, exception) -> {
|
response.setStatus(403);
|
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
objectMapper.writeValue(response.getWriter(), ApiResponse.failure(403, "无权访问"));
|
}).and()
|
.authorizeRequests()
|
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
.antMatchers("/api/admin/auth/login", "/api/mini/auth/wechat-phone-login",
|
"/api/guide/auth/login", "/api/guide/auth/password-login", "/api/guide/auth/sms-code",
|
"/api/health").permitAll()
|
.antMatchers("/api/guide/registration/**").permitAll()
|
.antMatchers(HttpMethod.GET, "/uploads/avatars/**").permitAll()
|
.antMatchers("/uploads/guide-applications/**").hasRole("ADMIN")
|
.antMatchers(HttpMethod.GET, "/api/mini/scenic-spots", "/api/mini/scenic-spots/**").permitAll()
|
.antMatchers(HttpMethod.GET, "/api/mini/agreements", "/api/mini/agreements/**").permitAll()
|
.antMatchers(HttpMethod.GET, "/api/guide/agreements", "/api/guide/agreements/**").permitAll()
|
.antMatchers("/api/admin/**").hasRole("ADMIN")
|
.antMatchers("/api/mini/**").hasRole("MINI_USER")
|
.antMatchers("/api/guide/**").hasRole("GUIDE_USER")
|
.anyRequest().authenticated().and()
|
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
|
return http.build();
|
}
|
|
@Bean
|
public CorsConfigurationSource corsConfigurationSource() {
|
CorsConfiguration configuration = new CorsConfiguration();
|
configuration.setAllowedOriginPatterns(Collections.singletonList("*"));
|
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
|
configuration.setAllowedHeaders(Collections.singletonList("*"));
|
configuration.setAllowCredentials(true);
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
source.registerCorsConfiguration("/**", configuration);
|
return source;
|
}
|
}
|