I've a year & a half old app to update. It was written in statemachine. Now I added a few things but the connectionRequest doesn't seem to work in iOS (which was built for iOS debug). I built it in android and it works very well.
public void connectionForLogin(String username, String password) {
ConnectionRequest cr = new ConnectionRequest() {
#Override
protected void readResponse(InputStream input) throws IOException {
JSONParser jSONParser = new JSONParser();
Map<String, Object> parsedData = jSONParser.parseJSON(new InputStreamReader(input));
ArrayList<Map<String, Object>> response = (ArrayList<Map<String, Object>>) parsedData.get("root");
if (response != null) {
for (Map<String, Object> element : response) {
success = (String) element.get("login");
msg = (String) element.get("msg");
ArrayList<Map<String, Object>> userInfoArray = (ArrayList) element.get("user_info");
Storage.getInstance().writeObject("userInfo", userInfoArray);
}
}
}
#Override
protected void postResponse() {
super.postResponse();
}
#Override
protected void handleErrorResponseCode(int code, String message) {
}
#Override
protected void handleException(Exception err) {
}
#Override
protected void handleIOException(IOException err) {
}
#Override
protected void handleRuntimeException(RuntimeException err) {
}
};
cr.setPost(true);
cr.setDuplicateSupported(true);
cr.setTimeout(30000);
AllUrl au = new AllUrl();
InfiniteProgress ip = new InfiniteProgress();
Dialog d = ip.showInifiniteBlocking();
cr.setDisposeOnCompletion(d);
cr.setUrl(http://zzz.com/api/logins/match? + "username=" + username + "&password=" + password);
NetworkManager.getInstance().addToQueueAndWait(cr);
}
This may be due to new Apple regulations that prevents apps from fetching data from non secure URL http. You can fix this temporarily by adding below build hint:
ios.plistInject=<key>NSAppTransportSecurity</key><dict><key>NSAllowsArbitraryLoads</key><true/></dict><key>CFBundleURLTypes</key><array><dict><key>CFBundleURLName</key><string>com.mycompany.myapp</string></dict><dict><key>CFBundleURLSchemes</key><array><string>MyApp</string></array></dict></array>
Note that your app may be rejected if connected to a non secure URL.
Related
I am using Solr 7.5 Server and I had used External Zookeeper.When I browse using the Solr Admin UI It ask authentication to me.
For Java Client I had used the below Code
BasicAuthSolrClientCache bs = new BasicAuthSolrClientCache("solr", "SolrRocks");
CloudSolrClient solrCloudClient = bs.getCloudSolrClient(zkHost);
solrCloudClient.setDefaultCollection("sample");
SolrInputDocument doc = new SolrInputDocument();
doc.addField("cat", "book");
doc.addField("id", "book-1");
doc.addField("name", "The Legend of the Hobbit part 1");
solrCloudClient.add(doc);
solrCloudClient.commit();
solrCloudClient.close();
BasicAuthSolrClientCache.java
public class BasicAuthSolrClientCache extends SolrClientCache {
private static final Logger log =
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final Map<String, SolrClient> solrClients = new HashMap<>();
private final String username;
private final String password;
public BasicAuthSolrClientCache(String username, String password) {
this.username = username;
this.password = password;
}
#Override
public synchronized CloudSolrClient getCloudSolrClient(String zkHost) {
CloudSolrClient client;
if (solrClients.containsKey(zkHost)) {
client = (CloudSolrClient) solrClients.get(zkHost);
} else {
client = new CloudSolrClient.Builder()
.withZkHost(zkHost)
.withHttpClient(getHttpClient())
.build();
client.connect();
solrClients.put(zkHost, client);
}
return client;
}
#Override
public synchronized HttpSolrClient getHttpSolrClient(String host) {
HttpSolrClient client;
if (solrClients.containsKey(host)) {
client = (HttpSolrClient) solrClients.get(host);
} else {
client = new HttpSolrClient.Builder(host)
.withHttpClient(getHttpClient())
.build();
solrClients.put(host, client);
}
return client;
}
#Override
public synchronized void close() {
for(Map.Entry<String, SolrClient> entry : solrClients.entrySet()) {
try {
entry.getValue().close();
} catch (IOException e) {
log.error("Error closing SolrClient for " + entry.getKey(), e);
}
}
solrClients.clear();
}
private HttpClient getHttpClient() {
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new
UsernamePasswordCredentials(this.username, this.password);
provider.setCredentials(AuthScope.ANY, credentials);
return
HttpClientBuilder.create().setDefaultCredentialsProvider(provider).
build();
}
}
But it give the exception like the below,
Exception in thread "main" org.apache.solr.client.solrj.impl.CloudSolrClient$RouteException: IOException occured when talking to server at: http://192.168.0.104:8983/solr/gettingstarted_shard2_replica1 at
How to authenticate SolrCloud using SolrJ
I found a easy way to do this.
You add a request interceptor like this so you do not have to worry about creating a properly configured HttpClient instance yourself. This will just add the interceptor to the default HttpClient that Solrj creates.
org.apache.solr.client.solrj.impl.HttpClientUtil.addRequestInterceptor(new SolrPreemptiveAuthInterceptor());
The RequestInterceptor looks like this:
public class SolrPreemptiveAuthInterceptor implements HttpRequestInterceptor {
final static Logger log = LoggerFactory.getLogger(SolrPreemptiveAuthInterceptor.class);
#Override
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
// If no auth scheme available yet, try to initialize it preemptively
if (authState.getAuthScheme() == null) {
log.info("No AuthState: set Basic Auth");
HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(HttpClientContext.CREDS_PROVIDER);
Credentials creds = credsProvider.getCredentials(authScope);
if(creds == null){
log.info("No Basic Auth credentials: add them");
creds = getCredentials(authScope);
}
authState.update(new BasicScheme(), creds);
}
}
private Credentials getCredentials(AuthScope authScope) {
String user = "";
String password = "";
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(user, password);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(authScope, creds);
log.info("Creating Basic Auth credentials for user {}", user);
return credsProvider.getCredentials(authScope);
}
}
You can also use UpdateRequest for indexing requests to do a basic authentication via SolrJ:
UpdateRequest ur = new UpdateRequest();
ur.add(doc);
ur.setBasicAuthCredentials("YOU USER NAME", "USER PASSWORD");
ur.setCommitWithin(COMMIT_WITHIN_INTERVAL);
ur.process(cloudSolrClient);
I've a error thrown I can't figure out how it happens. It doesn't occur all the time but once in a while. The error message thrown is "Java.lang.nullPointerException: Attempt to invoke virtual method 'boolean java.util.ArrayList.add(java.lang.Object)' on a null object reference". I've used connectionRequest for parsing the json data. When the error is thrown I've checked if there's problem in url but it gives the proper json data as always. After trying few times, the error is solved automatically.
if (!regNOField.getText().equals("") && !newPasswordField.getText().equals("")) {
ArrayList<Map<String, String>> argumentsArrayList = new ArrayList<>();
Map argumentMap1 = new HashMap();
argumentMap1.put("argument", "reg_no");
argumentMap1.put("value", regNOField.getText().trim());
argumentsArrayList.add(argumentMap1);
Map argumentMap2 = new HashMap();
argumentMap2.put("argument", "token");
argumentMap2.put("value", newPasswordField.getText().trim());
argumentsArrayList.add(argumentMap2);
CommonMethod.connectionMethod(res, true, url, "Verification", argumentsArrayList, true, null);
}
CommonMethod.connectionMethod:
public static void connectionMethod(Resources res, Boolean postBoolean, String urlString, String form, ArrayList<Map<String, String>> arguments,
Boolean ipFlag, String extraData) {
ConnectionRequest cr = new ConnectionRequest() {
#Override
protected void readResponse(InputStream input) throws IOException {
JSONParser jp = new JSONParser();
parser = jp.parseJSON(new InputStreamReader(input));
response = null;
if (parser != null && !parser.isEmpty()) {
if (parser.get("status").equals("true")) {
message = (String) parser.get("data");
ToastBar.getInstance().setPosition(Component.TOP);
ToastBar.showErrorMessage(message, 5000);
if (form.equals("Verification")) {
if (d != null) {
d.dispose();
}
new LoginAndSignUp(res, message).show();
}
}
}
}
#Override
protected void handleErrorResponseCode(int code, String message) {
System.out.println("login ErrorResponseCode " + code + "msg: " + message);
}
#Override
protected void handleException(Exception err) {
System.out.println("login Exception " + err);
}
#Override
protected void handleIOException(IOException err) {
System.out.println("login IOException " + err);
}
#Override
protected void handleRuntimeException(RuntimeException err) {
System.out.println("RuntimeException " + err);
}
};
cr.setPost(postBoolean);
cr.setUrl(urlString);
cr.setTimeout(80000);
if (arguments != null && !postBoolean.equals(false)) {
for (Map<String, String> entrySet : arguments) {
String argument1 = (String) entrySet.get("argument");
String value1 = (String) entrySet.get("value");
cr.addArgument(argument1, value1);
}
}
InfiniteProgress ip = new InfiniteProgress();
d = ip.showInifiniteBlocking();
cr.setDisposeOnCompletion(d);
cr.addRequestHeader("accept", "application/json");
NetworkManager.getInstance().addToQueueAndWait(cr);
}
Error msg:
I called 'new NewForm(res).show()' in postResponse but though the connection succeed, the particular form is not seen. I found out that if I comment out 'cr.setDisposeOnCompletion(d)', then it works fine.
But infinite progress runs infinitely if any exception occurs and so on. Is this a bug? It occured after I updated to new cn1 library update. If you want to see the project, its here:
https://drive.google.com/file/d/0B8ATnICIY2S8LUdta0F5NXYzamM/view?usp=sharing
Button checkButton = new Button("Check");
checkButton.addActionListener(e -> {
ConnectionCheck cc = new ConnectionCheck(theme);
cc.connectionCheckMethod();
});
ConnectionCheck class
public class ConnectionCheck {
Resources res;
Dialog d;
public ConnectionCheck(Resources res) {
this.res = res;
}
public void connectionCheckMethod() {
ConnectionRequest cr = new ConnectionRequest() {
#Override
protected void readResponse(InputStream input) throws IOException {
JSONParser jsonp = new JSONParser();
Map<String, Object> parser = jsonp.parseJSON(new InputStreamReader(input));
System.out.println("bibek " + parser);
}
#Override
protected void postResponse() {
new NewForm(res).show();
// d.dispose();
}
#Override
protected void handleErrorResponseCode(int code, String message) {
System.out.println("login ErrorResponseCode " + code + "msg: " + message);
// d.dispose();
}
#Override
protected void handleException(Exception err) {
System.out.println("login Exception " + err);
// d.dispose();
}
#Override
protected void handleIOException(IOException err) {
System.out.println("login IOException " + err);
// d.dispose();
}
#Override
protected void handleRuntimeException(RuntimeException err) {
System.out.println("login RuntimeException " + err);
// d.dispose();
}
};
cr.setPost(true);
cr.setUrl("http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo");
cr.setTimeout(30000);
cr.addRequestHeader("Accept", "application/json");
InfiniteProgress ip = new InfiniteProgress();
d = ip.showInifiniteBlocking();
cr.setDisposeOnCompletion(d); //if this line is commented, the newForm is shown
NetworkManager.getInstance().addToQueueAndWait(cr);
}
}
NewForm class
public class NewForm extends Form{
public NewForm(Resources res){
setTitle("new Form");
add(new Label("new Form"));
}
}
You need to dispose the dialog before calling the show of the new form. Dispose on completion will dispose the dialog when the connection is done which is sometimes unpredictable.
When a dialog is disposed it returns to the previous form i.e. the one shown before the dialog was shown.
Have a problem with CORS filter, i think.
Because when i send request with Authorization header by Intellij Idea REST Tools, my filter catch a Authorization header.
But when i try to send request from client side from another server, filter does not see my header(return null).
I`m using spring boot, angularjs, salelizer and JWT for build token.
Params for building token on server side.
private static final JWSHeader JWT_HEADER = new JWSHeader(JWSAlgorithm.HS256);
private static final String TOKEN_SECRET = "Bearer";
public static final String AUTH_HEADER_KEY = "Authorization";
My Auth filter
public class AuthFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String authHeader = httpRequest.getHeader(AuthUtils.AUTH_HEADER_KEY);
if (StringUtils.isBlank(authHeader) || authHeader.split(" ").length != 2) {
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, AUTH_ERROR_MSG);
} else {
JWTClaimsSet claimSet = null;
try {
claimSet = (JWTClaimsSet) AuthUtils.decodeToken(authHeader);
} catch (ParseException e) {
httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, JWT_ERROR_MSG);
return;
} catch (JOSEException e) {
httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, JWT_INVALID_MSG);
return;
}
// ensure that the token is not expired
if (new DateTime(claimSet.getExpirationTime()).isBefore(DateTime.now())) {
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, EXPIRE_ERROR_MSG);
} else {
chain.doFilter(request, response);
}
}
}
#Override
public void destroy() { /* unused */ }
#Override
public void init(FilterConfig filterConfig) throws ServletException { /* unused */ }
}
My CORS filter in Web Mvc config file
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addExposedHeader("Authorization");
config.addExposedHeader("Content-Type");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
My security configure
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"**").permitAll().and().authorizeRequests()
.antMatchers( "/index","/api/**", "/auth/**", "/js/**", "/css/**", "/html/**")
.permitAll().anyRequest().authenticated();
My cliend side configs
function configHttp($httpProvider, $authProvider){
console.log("sdfd");
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
$httpProvider.defaults.headers.common["Accept"] = "application/json";
$httpProvider.defaults.headers.common["Content-Type"] = "application/json";
var token = sessionStorage.getItem("satellizer_token");
if (token && $authProvider.httpInterceptor) {
token = $authProvider.authHeader === 'Authorization' ? 'Bearer ' + token : token;
$httpProvider.defaults.headers.common[$authProvider.authHeader] = token;
}
}
function configAuth($authProvider) {
$authProvider.httpInterceptor = function() { return true; };
$authProvider.baseUrl = 'http://localhost:8080';
$authProvider.loginUrl = '/auth/login';
$authProvider.signupUrl = '/auth/registration';
$authProvider.tokenName = 'token';
$authProvider.storageType = 'sessionStorage';
$authProvider.authToken = 'Bearer';
$authProvider.authHeader = 'Authorization';
}
There are a few options described here.
One option would be to annotate your controller method or class with #CrossOrigin.
If you want global config, you could add a new bean. I took this from the Spring doc listed above and modified it so that the mapping is /*. You can modify that path to be suitable for your application. According to the javadoc all origins will be allowed by default.
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*");
}
};
}
I have quite a simple question really.
I wrote a servlet for suppliers to upload XML-files to.
These files get written to a location on the server.
All the files get renamed with a timestamp.
Is there a risk of concurrency problems with the code below?
I ask because we receive files from a supplier, that look like
they have content from 2 different XML-files
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
public String getServletInfo() {
return "Short description";
}// </editor-fold>
protected void processRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
File dirToUse;
boolean mountExists = this.getDirmount().exists();
if (!mountExists) {
this.log("MOUNT " + this.getDirmount() + " does not exist!");
dirToUse = this.getDiras400();
} else {
dirToUse = this.getDirmount();
}
boolean useSimpleRead = true;
if (request.getMethod().equalsIgnoreCase("POST")) {
useSimpleRead = !ServletFileUpload.isMultipartContent(request);
}
if (useSimpleRead) {
this.log("Handle simple request.");
handleSimpleRequest(request, response, dirToUse);
} else {
this.log("Handle Multpart Post request.");
handleMultipart(request, response, dirToUse);
}
}
protected void handleMultipart(HttpServletRequest request,
HttpServletResponse response, File dir) throws IOException,
ServletException {
try {
FileItemFactory fac = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(fac);
List<FileItem> items = upload.parseRequest(request);
if (items.isEmpty()) {
this.log("No content to read in request.");
throw new IOException("No content to read in request.");
}
boolean savedToDisk = true;
Iterator<FileItem> iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
getFilename(request);
File diskFile = new File(dir, this.getFilename(request));
item.write(diskFile);
if (!diskFile.exists()) {
savedToDisk = false;
}
}
if (!savedToDisk) {
throw new IOException("Data not saved to disk.");
}
} catch (FileUploadException fue) {
throw new ServletException(fue);
} catch (Exception e) {
throw new IOException(e.getMessage());
}
}
protected void handleSimpleRequest(HttpServletRequest request,
HttpServletResponse response, File dir) throws IOException {
// READINPUT DATA TO STRINGBUFFER
InputStream in = request.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuffer sb = new StringBuffer();
String line = reader.readLine();
while (line != null) {
sb.append(line + "\r\n");
line = reader.readLine();
}
if (sb.length() == 0) {
this.log("No content to read in request.");
throw new IOException("No content to read in request.");
}
//Get new Filename
String newFilename = getFilename(request);
File diskFile = new File(dir, newFilename);
saveDataToFile(sb, diskFile);
if (!diskFile.exists()) {
throw new IOException("Data not saved to disk.");
}
}
protected abstract String getFilename(HttpServletRequest request);
protected void saveDataToFile(StringBuffer sb, File diskFile) throws IOException {
BufferedWriter out = new BufferedWriter(new FileWriter(diskFile));
out.write(sb.toString());
out.flush();
out.close();
}
getFileName implementation:
#Override
protected String getFilename(HttpServletRequest request) {
Calendar current = new GregorianCalendar(TimeZone.getTimeZone("GMT+1"));
long currentTimeMillis = current.getTimeInMillis();
System.out.println(currentTimeMillis);
return "disp_" + request.getRemoteHost() + "_" + currentTimeMillis + ".xml";
}
Anyway, thanks in advance!
There would not be synchronization problems but there can be race conditions, for example, two threads might return the same file name using the method getFileName()