后端用springboot + spring security4 + JWT,前端用vue.js+axios发送post老是请求失败,在网上查了各种文章,问题最终解决。
1,首先在继承于WebSecurityConfigurerAdapter类的子类中(我的是WebSecurityConfig)设置cors属性。
package com.example.securitydemoserver.config.security
import com.example.securitydemoserver.config.jwt.JWTAuthenticationFilter
import com.example.securitydemoserver.config.jwt.JWTAuthorizationFilter
import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.builders.WebSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import javax.servlet.http.HttpServletResponse
import org.apache.commons.logging.LogFactory
import org.springframework.boot.web.servlet.FilterRegistrationBean
import org.springframework.http.HttpMethod
import org.springframework.security.config.http.SessionCreationPolicy
@Configuration
@EnableWebSecurity//开启spring security 功能
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)//开启spring security 注解,如@PreAuthorize,@PreFilter等
class WebSecurityConfig: WebSecurityConfigurerAdapter() {
val objectMapper= ObjectMapper();
val logger=LogFactory.getLog(WebSecurityConfig::class.java)
@Autowired
lateinit var myUserDetailsService: MyUserDetailsService
override fun configure(http: HttpSecurity) {
http
//开启模拟请求,比如API POST测试工具的测试,不开启时,API POST为报403错误
.csrf().disable()
//开启跨域访问.cors()**********************我在这里*****************
.cors()
.and()
.httpBasic()
//未登录时,进行json格式的提示,很喜欢这种写法,不用单独写一个又一个的类
.authenticationEntryPoint { request, response, authException ->
response.setContentType("application/json;charset=utf-8");
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
var out = response.getWriter();
var map = mutableMapOf<String, Any>();
map.put("code", 403);
map.put("message", "未登录");
out.write(objectMapper.writeValueAsString(map));
out.flush();
out.close();
}
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.addFilter(JWTAuthenticationFilter(authenticationManager()))
.addFilter(JWTAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
}
/*身份认证*/
override fun configure(auth: AuthenticationManagerBuilder) {
auth.userDetailsService(myUserDetailsService).passwordEncoder(BCryptPasswordEncoder())
}
override fun configure(web: WebSecurity) {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**")
}
/*必须要有这个bean告诉spring密码的加密方式*/
@Bean
fun passwordEncoder() = BCryptPasswordEncoder()
}
若不设置cors或设置为cors().disable()则报错
Access to XMLHttpRequest at 'http://localhost:8090/api/login' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
2,添加跨域配置
package com.example.securitydemoserver.config
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.cors.CorsConfiguration
import org.springframework.web.cors.UrlBasedCorsConfigurationSource
import org.springframework.web.filter.CorsFilter
/**
* springboot + security +jwt跨域请求配置*/
@Configuration
class CorsConfig {
private fun buildConfig(): CorsConfiguration{
var corsConfiguration = CorsConfiguration();
corsConfiguration.addAllowedOrigin("*")
corsConfiguration.addAllowedHeader("*")
corsConfiguration.addAllowedMethod("*")
corsConfiguration.allowCredentials
return corsConfiguration
}
@Bean
fun corsFilter(): CorsFilter {
var source = UrlBasedCorsConfigurationSource();
//可以访问的地址
source.registerCorsConfiguration("/**",buildConfig())
return CorsFilter(source)
}
}
若无以上配置则报错:Access to XMLHttpRequest at 'http://localhost:8090/api/login' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.3
3,接着就需要在前端的访问加上请求头。
方法一:
const instance = axios.create({
baseURL: 'http://localhost:8090',
headers: {
'Access-Control-Allow-Origin': '*'
}
});
方法二:
const instance = axios.create({
baseURL: 'http://localhost:8090',
});
instance.interceptors.request.use((config) => {
config.headers['X-Client'] = _.get(store, 'state.app.code');
config.headers['Access-Control-Allow-Origin'] = '*'
return config;
});
如果框架是springboot+security4+JWT的话基本就没啥子问题了,