[英]How to access url from another origin? Preflight request returns 401 even if Access-Control-Allow-* headers is present
I run simple Jersey REST endpoint in embedded jetty with basic authentication and try to access it via ajax call from other web-application. 我使用基本身份验证在嵌入式码头中运行简单的Jersey REST端点,并尝试通过其他Web应用程序通过ajax调用来访问它。 But I get 401 Unauthorized on preflight request even if Access-Control-Allow-* headers is present. 但是,即使存在Access-Control-Allow- *标头,我也会在预检请求中得到401未经授权 。
Server code: 服务器代码:
public final class RESTServerStarter {
private static final int WEB_SERVER_PORT = 8888;
public static void main(String[] args) throws Exception {
final ServletHolder sh = new ServletHolder(ServletContainer.class);
sh.setInitParameter(ServletContainer.RESOURCE_CONFIG_CLASS, PackagesResourceConfig.class.getCanonicalName());
sh.setInitParameter(PackagesResourceConfig.PROPERTY_PACKAGES, HelloRESTService.class.getPackage().getName());
final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setSecurityHandler(basicAuth("admin", "adminpwd", "Private!"));
context.setContextPath("/rest");
context.addServlet(sh, "/*");
context.addFilter(MyFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
final Server server = new Server();
final ServerConnector connector = new ServerConnector(server);
connector.setHost("172.18.133.20");
connector.setPort(WEB_SERVER_PORT);
server.addConnector(connector);
server.setHandler(context);
try {
server.start();
server.join();
} finally {
server.destroy();
}
}
private static final SecurityHandler basicAuth(String username, String password, String realm) {
HashLoginService hashLoginService = new HashLoginService();
hashLoginService.putUser(username, Credential.getCredential(password), new String[]{"user"});
hashLoginService.setName(realm);
Constraint constraint = new Constraint();
constraint.setName(Constraint.__BASIC_AUTH);
constraint.setRoles(new String[]{"user"});
constraint.setAuthenticate(true);
ConstraintMapping cm = new ConstraintMapping();
cm.setConstraint(constraint);
cm.setPathSpec("/*");
ConstraintSecurityHandler csh = new ConstraintSecurityHandler();
csh.setAuthenticator(new BasicAuthenticator());
csh.setRealmName("myrealm");
csh.addConstraintMapping(cm);
csh.setLoginService(hashLoginService);
return csh;
}
public static final class MyFilter implements Filter {
public void init(FilterConfig filterConfig) {
//nothing to init
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
final HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.addHeader("Access-Control-Allow-Origin", "http://172.18.133.20:" + RESTClientStarter.WEB_SERVER_PORT);
httpResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE, PUT");
httpResponse.addHeader("Access-Control-Allow-Credentials", "true");
httpResponse.addHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
chain.doFilter(request, response);
}
public void destroy() {
//nothing to destroy
}
}
@Path("/test")
public static class HelloRESTService {
@GET
@Path("hello")
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "hello";
}
}
} }
Client code: 客户代码:
$(function(){
$.ajax({
url : "http://172.18.133.20:8888/rest/test/hello",
type : "GET",
timeout : 120000,
async : true,
xhrFields: {
withCredentials: true
},
crossDomain: true,
headers: {
"Authorization": "Basic " + btoa("admin:adminpwd")
},
error: function(xhr, status, error) {
$("#container").text(error);
},
success: function(xhr) {
$("#container").text(xhr);
}
});
});
Client code run on http://172.18.133.20:9999 客户端代码在http://172.18.133.20:9999上运行
Here is the full sources: 以下是全部资料:
https://bitbucket.org/dmitry_apanasevich/cors/src https://bitbucket.org/dmitry_apanasevich/cors/src
Could you please tell me what's wrong? 你能告诉我怎么了吗?
Thanks for advance! 感谢前进!
I have solved the problen excluding OPTIONS request from SecurityMapping. 我已经解决了从SecurityMapping排除OPTIONS请求的问题。 Just adding one line: 只需添加一行:
...
ConstraintMapping cm = new ConstraintMapping();
cm.setMethod("GET"); //new line
cm.setConstraint(constraint);
cm.setPathSpec("/*");
...
I think you use httpResponse.addHeader("Access-Control-Allow-Origin", " http://172.18.133.20 :" + RESTClientStarter.WEB_SERVER_PORT); 我认为您使用httpResponse.addHeader(“ Access-Control-Allow-Origin”,“ http://172.18.133.20 :” + RESTClientStarter.WEB_SERVER_PORT); and WEB_SERVER_PORT of your rest app is 9999 so httpResponse allow http://172.18.133.20:9999 . 其余应用程序的WEB_SERVER_PORT是9999,因此httpResponse允许http://172.18.133.20:9999 。 But you call it at port 8888 this is not allow. 但是您不允许在端口8888上调用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.