私はこのJetty組み込みサーバーを自分のlocalhost:8008に持っており、それにアクセスするlocalhost:4200に別のAngularアプリケーションを持っています。次のコードでCORSを使用して、CrossOriginFilterをこのsvrContextに追加することができました(これは私のwebservicesの場所です)。Jetty Embedded:CORS +基本認証(ConstraintSecurityHandler)を使用
しかし、私は真にこの安全なブール値を設定した場合、私の角度アプリケーションは以下のようにメッセージを与える:プリフライトリクエストに
OPTIONS http://localhost:8008/server/admin/session 401 (Unauthorized) scheduleTask @ zone.js:2263 webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:410 onScheduleTask @ zone.js:300 webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:404 webpackJsonp.../../../../zone.js/dist/zone.js.Zone.scheduleTask @ zone.js:235 webpackJsonp.../../../../zone.js/dist/zone.js.Zone.scheduleMacroTask @ zone.js:258 (anonymous) @ zone.js:2287 proto.(anonymous function) @ zone.js:1426 (anonymous) @ http.es5.js:1275 webpackJsonp.../../../../rxjs/Observable.js.Observable._trySubscribe @ Observable.js:57 webpackJsonp.../../../../rxjs/Observable.js.Observable.subscribe @ Observable.js:45 webpackJsonp.../../../../rxjs/operator/map.js.MapOperator.call @ map.js:54 webpackJsonp.../../../../rxjs/Observable.js.Observable.subscribe @ Observable.js:42 webpackJsonp.../../../../../src/app/login/login.component.ts.LoginComponent.loginAdmin @ login.component.ts:42 (anonymous) @ LoginComponent.html:3 handleEvent @ core.es5.js:12076 callWithDebugContext @ core.es5.js:13535 debugHandleEvent @ core.es5.js:13123 dispatchEvent @ core.es5.js:8688 (anonymous) @ core.es5.js:10850 schedulerFn @ core.es5.js:3647 webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.__tryOrUnsub @ Subscriber.js:238 webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.next @ Subscriber.js:185 webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber._next @ Subscriber.js:125 webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next @ Subscriber.js:89 webpackJsonp.../../../../rxjs/Subject.js.Subject.next @ Subject.js:55 webpackJsonp.../../../core/@angular/core.es5.js.EventEmitter.emit @ core.es5.js:3621 webpackJsonp.../../../forms/@angular/forms.es5.js.FormGroupDirective.onSubmit @ forms.es5.js:4801 (anonymous) @ LoginComponent.html:3 handleEvent @ core.es5.js:12076 callWithDebugContext @ core.es5.js:13535 debugHandleEvent @ core.es5.js:13123 dispatchEvent @ core.es5.js:8688 (anonymous) @ core.es5.js:9299 (anonymous) @ platform-browser.es5.js:2668 webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:424 onInvokeTask @ core.es5.js:3924 webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:423 webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask @ zone.js:191 ZoneTask.invoke @ zone.js:486 login:1 XMLHttpRequest cannot load http://localhost:8008/server/admin/session.
応答は、アクセス制御チェックに合格しない:いいえ 「Access-Control-Allow-Origin」ヘッダーは、要求された リソースに存在します。したがって、「http://localhost:4200」の原点は許可されません。 応答にはHTTPステータスコード401が付きました。
何が欠けていますか?私は別々に使用することができました - 同じ原点アプリケーションを持つSecurtiyHandlerと(基本認証をオフにして)クロスオリジン要求。
public class JettyLauncher {
private static Server server;
private static Boolean prod = true;
private static String protocol = "https";
private static String host = "localhost";
private static int port = 8080;
private static String staticContent = "";
private static String services = "";
private static Boolean secure = true;
public static Resystoken tokenClass;
private static String realm = "";
private static Boolean logToFile = false;
public static String url;
public static String usuario;
public static String senha;
public static void main(String[] args) throws Exception {
launch();
}
public static void launch() throws IOException, Exception{
String buildPath = new File("").getAbsolutePath();
System.out.println("* Build path: " + buildPath);
prod = Boolean.valueOf(PropertySource.props.getProperty("resysclagem.launch.prod"));
String sufixoProd = "";
if(prod){
System.out.println("* Production mode ON (Prod mode)");
sufixoProd = ".prod";
} else {
System.out.println("* Not prod application (Dev mode)");
}
services = PropertySource.props.getProperty("resysclagem.launch.services");
staticContent = PropertySource.props.getProperty("resysclagem.webapps");
secure = Boolean.valueOf(PropertySource.props.getProperty("resysclagem.launch.security.basicauth"));
realm = PropertySource.props.getProperty("resysclagem.realm.props");
logToFile = Boolean.valueOf(PropertySource.props.getProperty("resysclagem.launch.logtofile"));
tokenClass = new Resystoken(
PropertySource.props.getProperty("resysclagem.launch.token.key"),
Boolean.valueOf(PropertySource.props.getProperty("resysclagem.launch.security.requiretoken"))
);
url = PropertySource.props.getProperty("resysclagem.bd"+ sufixoProd +".url");
usuario = PropertySource.props.getProperty("resysclagem.bd"+ sufixoProd +".usuario");
senha = PropertySource.props.getProperty("resysclagem.bd"+ sufixoProd +".senha"); // pensar em em maneira de encriptar
protocol = PropertySource.props.getProperty("resysclagem.launch"+ sufixoProd +".protocol");
host = PropertySource.props.getProperty("resysclagem.launch"+ sufixoProd +".host");
if(!host.equalsIgnoreCase("localhost")) {
host = Inet4Address.getLocalHost().getHostAddress();
}
try {
port = Integer.valueOf(PropertySource.props.getProperty("resysclagem.launch"+ sufixoProd +".port"));
} catch(NumberFormatException nfe){
String strPort = PropertySource.props.getProperty("resysclagem.launch"+ sufixoProd +".port");
if(strPort.equalsIgnoreCase("heroku")){
port = Integer.valueOf(System.getenv("PORT"));
}
}
server = new Server(port);
HandlerList a = new HandlerList();
HttpConfiguration http_config = new HttpConfiguration();
SslContextFactory sslContextFactory = new SslContextFactory();
if(protocol.equalsIgnoreCase("https")){
port = port + 1;
// https://github.com/eclipse/jetty.project/blob/jetty-9.3.x/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java
// HTTP Configuration
http_config.setSecureScheme("https");
http_config.setSecurePort(port); // port 8443
http_config.setOutputBufferSize(32768);
http_config.setRequestHeaderSize(8192);
http_config.setResponseHeaderSize(8192);
http_config.setSendServerVersion(true);
http_config.setSendDateHeader(false);
// SSL Context Factory
String keystorePath = buildPath + File.separator + "resources" + File.separator + "reskey";
File f = new File(keystorePath);
if(!f.exists()) {
throw new Exception("File doesn't exist at "+ keystorePath);
}
sslContextFactory.setKeyStorePath(keystorePath);
String obf = Password.obfuscate("resysadmin*$");
sslContextFactory.setKeyStorePassword(obf);
sslContextFactory.setKeyManagerPassword(obf);
sslContextFactory.setTrustStorePath("resources" + File.separator + "/reskey");
sslContextFactory.setTrustStorePassword("resysadmin*$");
sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA", "SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
// SSL HTTP Configuration
HttpConfiguration https_config = new HttpConfiguration(http_config);
https_config.addCustomizer(new SecureRequestCustomizer());
// SSL Connector
ServerConnector sslConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(https_config));
sslConnector.setPort(port); // 8443
server.addConnector(sslConnector);
}
//static content
ResourceHandler resourceHandler= new ResourceHandler();
resourceHandler.setResourceBase(staticContent); // webapps
resourceHandler.setDirectoriesListed(true);
resourceHandler.setWelcomeFiles(new String[]{"index.html"});
ContextHandler webContext = new ContextHandler("/"); /* the server uri path */
webContext.setHandler(resourceHandler);
//webservices
ResourceConfig config = new ResourceConfig();
config.register(MultiPartFeature.class);
config.packages("resysclagem.ws.services");
config.register(JacksonFeature.class);
ServletHolder servlet = new ServletHolder(new ServletContainer(config));
ServletContextHandler svrContext = new ServletContextHandler(server, services); //context path, services == /server
svrContext.addServlet(servlet, "/*"); //server/endpoints
svrContext.setInitParameter("jersey.config.server.provider.packages", "com.jersey.jaxb,com.fasterxml.jackson.jaxrs.json");
svrContext.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");
/*
* TODO aqui: posteriormente, autorizar apenas o domínio do módulo WEB a fazer alterações aqui
*/
FilterHolder holder = new FilterHolder(new CrossOriginFilter());
holder.setInitParameter("allowedMethods", "GET,POST,PUT,DELETE,HEAD,OPTIONS");
//holder.setInitParameter("allowedOrigins", "http://localhost:4200");
holder.setInitParameter("allowedHeaders", "Content-Type, Accept, X-Requested-With");
svrContext.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST));
a.addHandler(webContext); // index
a.addHandler(svrContext);
// basic authentication - ver resysclagem.realm.props
if (secure){
HashLoginService loginService = new HashLoginService("ResysRealm",
realm);
server.addBean(loginService);
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
// This constraint requires authentication and in addition that an
// authenticated user be a member of a given set of roles for
// authorization purposes.
Constraint constraint = new Constraint();
constraint.setName("auth");
constraint.setAuthenticate(true);
constraint.setRoles(new String[] { "user", "admin" });
// Binds a url pattern with the previously created constraint. The roles
// for this constraing mapping are mined from the Constraint itself
// although methods exist to declare and bind roles separately as well.
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec("/*");
mapping.setConstraint(constraint);
security.setConstraintMappings(Collections.singletonList(mapping));
security.setAuthenticator(new BasicAuthenticator()); //base64
security.setLoginService(loginService);
/*
HashLoginService login = new HashLoginService();
login.setName("Test Realm");
login.setConfig("./resources/realm.properties");
login.setHotReload(false);
server.addBean(login);
*/
security.setHandler(a);
server.setHandler(security);
} else {
System.out.println("* Warn: services and static content are not secured by authentication");
server.setHandler(a);
}
try {
if(logToFile){
System.out.println("* From here, output will be printed on log file instead of console.");
PrintStream out = new PrintStream(new FileOutputStream("launchLog.txt"));
System.setOut(out);
}
server.start();
System.out.println("* Up at "+ host +":"+ port);
server.join();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
}
}
public static boolean isRunning() {
if (server == null){
return false;
}
return server.isRunning();
}
}
(プリフライトメッセージに使用されるOPTIONSのような)一部のリクエストのみがSecurityHandlerをバイパスできるようにする方法はありますか?私はあなたの答えが受け入れられるほど明確になっていると思うので、カスタムコードを試してみます:) –
@RodrigoNantes:OPTIONSリクエストのSecurityHandlerをバイパスする方法があると確信していますが、試してみる。 : - \私は掲示板に掲示し、回答があった場合はここに返信することをお勧めします。 ;)私はプログラム的に模倣しようとしたいくつかの高度なweb.xmlの例を見てきましたが、運はありません。 –