Ara*_*yan 26 java spring-security cors
我正在努力让CORS与Spring Security很好地配合,但它并不符合.我做了本文中描述的更改并更改此行applicationContext-security.xml已经有POST和GET请求适用于我的应用程序(暂时公开控制器方法,所以我可以测试CORS):
<intercept-url pattern="/**" access="isAuthenticated()" /><intercept-url pattern="/**" access="permitAll" />不幸的是,通过AJAX允许Spring Security登录的以下URL没有响应:http://localhost:8080/mutopia-server/resources/j_spring_security_check.我正在从AJAX请求http://localhost:80到http://localhost:8080.
在尝试访问时,j_spring_security_check我(pending)在Chrome中获取OPTIONS预检请求,并且AJAX调用返回HTTP状态代码0和消息"错误".
预检成功使用HTTP状态代码302,然后我仍然直接获得我的AJAX请求的错误回调,其中HTTP状态为0,消息为"error".


function get(url, json) {
var args = {
type: 'GET',
url: url,
// async: false,
// crossDomain: true,
xhrFields: {
withCredentials: false
},
success: function(response) {
console.debug(url, response);
},
error: function(xhr) {
console.error(url, xhr.status, xhr.statusText);
}
};
if (json) {
args.contentType = 'application/json'
}
$.ajax(args);
}
function post(url, json, data, dataEncode) {
var args = {
type: 'POST',
url: url,
// async: false,
crossDomain: true,
xhrFields: {
withCredentials: false
},
beforeSend: function(xhr){
// This is always added by default
// Ignoring this prevents preflight - but expects browser to follow 302 location change
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader("X-Ajax-call", "true");
},
success: function(data, textStatus, xhr) {
// var location = xhr.getResponseHeader('Location');
console.error('success', url, xhr.getAllResponseHeaders());
},
error: function(xhr) {
console.error(url, xhr.status, xhr.statusText);
console.error('fail', url, xhr.getAllResponseHeaders());
}
}
if (json) {
args.contentType = 'application/json'
}
if (typeof data != 'undefined') {
// Send JSON raw in the body
args.data = dataEncode ? JSON.stringify(data) : data;
}
console.debug('args', args);
$.ajax(args);
}
var loginJSON = {"j_username": "username", "j_password": "password"};
// Fails
post('http://localhost:8080/mutopia-server/resources/j_spring_security_check', false, loginJSON, false);
// Works
post('http://localhost/mutopia-server/resources/j_spring_security_check', false, loginJSON, false);
// Works
get('http://localhost:8080/mutopia-server/landuses?projectId=6', true);
// Works
post('http://localhost:8080/mutopia-server/params', true, {
"name": "testing",
"local": false,
"generated": false,
"project": 6
}, true);
Run Code Online (Sandbox Code Playgroud)
请注意 - 除了Spring Security登录,我可以通过CORS POST到我的应用程序中的任何其他URL.我已经阅读了很多文章,所以对这个奇怪问题的任何见解将不胜感激
Kee*_*eth 20
我能够通过扩展UsernamePasswordAuthenticationFilter来实现这一点......我的代码在Groovy中,希望没关系:
public class CorsAwareAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
static final String ORIGIN = 'Origin'
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response){
if (request.getHeader(ORIGIN)) {
String origin = request.getHeader(ORIGIN)
response.addHeader('Access-Control-Allow-Origin', origin)
response.addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
response.addHeader('Access-Control-Allow-Credentials', 'true')
response.addHeader('Access-Control-Allow-Headers',
request.getHeader('Access-Control-Request-Headers'))
}
if (request.method == 'OPTIONS') {
response.writer.print('OK')
response.writer.flush()
return
}
return super.attemptAuthentication(request, response)
}
}
Run Code Online (Sandbox Code Playgroud)
以上重点:
您需要在Spring配置中声明此bean.有很多文章展示了如何做到这一点,所以我不会在这里复制.
在我自己的实现中,我使用原始域白名单,因为我只允许CORS进行内部开发人员访问.以上是我正在做的简化版本,因此可能需要调整,但这应该给你一般的想法.
aze*_*ati 16
这是我的代码工作得很好,对我来说很完美:我花了两天时间研究它并理解弹簧安全性所以我希望你接受它作为答案,哈哈
public class CorsFilter extends OncePerRequestFilter {
static final String ORIGIN = "Origin";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
System.out.println(request.getHeader(ORIGIN));
System.out.println(request.getMethod());
if (request.getHeader(ORIGIN).equals("null")) {
String origin = request.getHeader(ORIGIN);
response.setHeader("Access-Control-Allow-Origin", "*");//* or origin as u prefer
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers",
request.getHeader("Access-Control-Request-Headers"));
}
if (request.getMethod().equals("OPTIONS")) {
try {
response.getWriter().print("OK");
response.getWriter().flush();
} catch (IOException e) {
e.printStackTrace();
}
}else{
filterChain.doFilter(request, response);
}
}
}
Run Code Online (Sandbox Code Playgroud)
那么你还需要设置你的过滤器来调用:
<security:http use-expressions="true" .... >
...
//your other configs
<security:custom-filter ref="corsHandler" after="PRE_AUTH_FILTER"/> // this goes to your filter
</security:http>
Run Code Online (Sandbox Code Playgroud)
那么你需要一个bean用于你创建的自定义过滤器:
<bean id="corsHandler" class="mobilebackbone.mesoft.config.CorsFilter" />
Run Code Online (Sandbox Code Playgroud)
Hen*_*wan 11
从Spring Security 4.1开始,这是使Spring Security支持CORS的正确方法(在Spring Boot 1.4/1.5中也需要):
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
}
Run Code Online (Sandbox Code Playgroud)
和:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// http.csrf().disable();
http.cors();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(ImmutableList.of("*"));
configuration.setAllowedMethods(ImmutableList.of("HEAD",
"GET", "POST", "PUT", "DELETE", "PATCH"));
// setAllowCredentials(true) is important, otherwise:
// The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
configuration.setAllowCredentials(true);
// setAllowedHeaders is important! Without it, OPTIONS preflight request
// will fail with 403 Invalid CORS request
configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Run Code Online (Sandbox Code Playgroud)
千万不能做任何的下方,这是错误的方式来尝试解决问题:
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();web.ignoring().antMatchers(HttpMethod.OPTIONS);参考:http://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/cors.html
大多数情况下,OPTIONS请求不带cookie来验证spring security.
要重新启用它,可以修改spring security的配置以允许OPTIONS请求而无需身份验证.
我研究了很多并得到两个解决方案:
1.使用带有Spring安全配置的Java配置,
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"/path/to/allow").permitAll()//allow CORS option calls
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
Run Code Online (Sandbox Code Playgroud)
2.使用XML(注意:不能写"POST,GET"):
<http auto-config="true">
<intercept-url pattern="/client/edit" access="isAuthenticated" method="GET" />
<intercept-url pattern="/client/edit" access="hasRole('EDITOR')" method="POST" />
<intercept-url pattern="/client/edit" access="hasRole('EDITOR')" method="GET" />
</http>
Run Code Online (Sandbox Code Playgroud)
最后,有解决方案的来源...... :)
| 归档时间: |
|
| 查看次数: |
51408 次 |
| 最近记录: |