How to disable springboot authentication for internal method invoke. [AuthenticationCredentialsNotFoundException] - java

I was trying to invoke all the controller methods when the service is up to warmup the cache.
But our methods has some permission control like:
#PreAuthorize(value = "hasPermission(#securedObject.application(), 'READ_PRODUCT')
The way how I invoke methods is like this:
private void adaptAndExecute(HandlerMethod handlerMethod, Map requestParas, List<Future> taskStaus) {
Object[] parameters = adaptParas(handlerMethod.getMethodParameters(), requestParas);
Object controllerInstance = applicationContext.getBean(handlerMethod.getBeanType());
taskStaus.add(pool.submit(() -> {
try {
handlerMethod.getMethod().invoke(controllerInstance, parameters);
} catch (Exception e) {
logger.warn("invoke method failed.", e);
}
}));
}
But I got this errors:
Caused by: org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:336)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:200)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:58)
So, how can I disable the authentication if I invoke internally?
Thanks
Currently I have no idea about this.

Related

Are the Azure Workload Identity (Client Assertion) tokens compatible with the msal4j token cache?

I'm trying to use the Azure Workload Identity MSAL Java Sample, and I'm trying to figure out if the built-in token cache that comes with MSAL4J is actually usable with Azure Workload Identity (Client Assertions), as my understanding is that every time you request a new token, you need to read the AZURE_FEDERATED_TOKEN_FILE again (See // 1). I've looked through the MSAL4J code and to me it looks like you'd need to throw away the ConfidentialClientApplication (see // 2) and create a brand new one to load in a new federated token file, because the clientAssertion ends up baked into the client. So then I'd need to do my own checks to figure out if I need if I need to recreate the client, basically defeating the purpose of the built-in client.
Are my assumptions correct? Or is there some way to hook into the token refresh process and reload the clientAssertion?
Maybe MSAL4J needs integrated token cache support for Azure Workload Identity that handles the reloading of the client assertion on renewal?
Here is the sample code included for context.
public class CustomTokenCredential implements TokenCredential {
public Mono<AccessToken> getToken(TokenRequestContext request) {
Map<String, String> env = System.getenv();
String clientAssertion;
try {
clientAssertion = new String(Files.readAllBytes(Paths.get(env.get("AZURE_FEDERATED_TOKEN_FILE"))),
StandardCharsets.UTF_8); // 1
} catch (IOException e) {
throw new RuntimeException(e);
}
IClientCredential credential = ClientCredentialFactory.createFromClientAssertion(clientAssertion);
String authority = env.get("AZURE_AUTHORITY_HOST") + env.get("AZURE_TENANT_ID");
try {
ConfidentialClientApplication app = ConfidentialClientApplication
.builder(env.get("AZURE_CLIENT_ID"), credential).authority(authority).build(); // 2
Set<String> scopes = new HashSet<>();
for (String scope : request.getScopes())
scopes.add(scope);
ClientCredentialParameters parameters = ClientCredentialParameters.builder(scopes).build();
IAuthenticationResult result = app.acquireToken(parameters).join();
return Mono.just(
new AccessToken(result.accessToken(), result.expiresOnDate().toInstant().atOffset(ZoneOffset.UTC)));
} catch (Exception e) {
System.out.printf("Error creating client application: %s", e.getMessage());
System.exit(1);
}
return Mono.empty();
}
}

How to handle Spring Data JPA deletes when deleting by PK that does not exist?

What is the best way to handle errors when using Spring's Jpa Repository deleteById(Long id) method?
By default the deleteById(), checks to see if the ID has an existing row in the database, if it doesn't it throws a org.springframework.dao.EmptyResultDataAccessException because it expects a row size of 1.
I first tried to use my Exception Handler to pick up on this exception, which worked fine but the message exposes my package and class name to the user when Spring returns the error message.
#ExceptionHandler(EmptyResultDataAccessException.class)
#ResponseStatus(HttpStatus.BAD_REQUEST)
protected ResponseEntity<RestApiError> handleEmptyResultDataAccessException(EmptyResultDataAccessException ex, HttpServletRequest request) {
RestApiError error = new RestApiError(HttpStatus.BAD_REQUEST, Map.of("message", ex.getMessage()), request.getRequestURI());
return new ResponseEntity<>(error, error.getHttpStatus());
}
ex.getMessage() returns:
No class net.demo.customerservice.model.CustomerLocation
entity with id 7 exists!
Instead I decided to catch EmptyResultDataAccessException, and then throw more useful exception and message where I call deleteById();
My current code:
public void delete(Long id) {
try {
repository.deleteById(id); // call Spring's Data JPA repository method deleteById
} catch (EmptyResultDataAccessException ex) {
throw new EntityNotFoundException("Location with ID: [" + id + "] was not found");
}
}
This works great, and returns a good error message to the user but it seems like a hack.
Is there any better way to handle the EmptyResultDataAccessException? I could also use the existsById() method before calling the delete method, but then I am using two queries.
Generally it's better to avoid catching exceptions throughout the code. If you can delegate exception handling to another class, you can handle errors consistently across your application in one place. You could use #ControllerAdvice for this:
#ControllerAdvice
class GlobalControllerExceptionHandler {
#ExceptionHandler(EmptyResultDataAccessException.class)
public ResponseEntity<> handleRecordNotFound(EmptyResultDataAccessException ex) {
LOG.trace("Record not found: {}", ex.getMessage());
RestApiError error = new RestApiError(HttpStatus.BAD_REQUEST, Map.of("message", "Record not found"), request.getRequestURI());
return new ResponseEntity<>(error, error.getHttpStatus());
}
}
The client knows which entity it requested to delete, so there's no need to include the id in the error message returned to the client. You could log the message with he id to the log file.

How to manage concurrent API Calls throughout the lifetime of an application

At the moment i am trying to find the best way to manage concurrent API Calls within my application. Currently i have been using HTTPURLConnection to make my HTTP method calls and although it works fine, eventually i would come across some 'Socket exception: connection reset' whilst calls are being made. however, i am using multithreading as i have many different api calls running concurrently.
I have looked into using AsyncRestTemplate and although it is working i find that in the console a list of the pool and thread is shown i.e [pool-6-thread-1] however when it becomes [pool-2018-thread-1] that is when it decides to stop making any more api calls.
This is the code that i am using:
//This method is inside another class in my actual application but here for simplicity
public static ListenableFuture<ResponseEntity<String>> getLastPrice( AsyncRestTemplate asyncRestTemplate) {
String url = "https://bittrex.com/api/v1.1/public/getmarketsummary?market=btc-dar";
asyncRestTemplate = new AsyncRestTemplate(new ConcurrentTaskExecutor(Executors.newCachedThreadPool()));
return asyncRestTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>("result"), String.class);
}
public PriceThread(JTextField lastPriceJT) {
this.lastPriceJT = lastPriceJT;
}
#Override
public void run() {
AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(new ThreadPoolTaskExecutor());
while (true) {
try {
getLastPrice(coin, asyncRestTemplate)
.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
#Override
public void onSuccess(ResponseEntity<String> response) {
//TODO: Add real response handling
try {
JSONObject result = new JSONObject(response.getBody());
String status = LOGGER.printResponseToLogger(result);
BigDecimal last = result.getJSONArray("result").getJSONObject(0).getBigDecimal("Last");
lastPriceJT.setText(last.toPlainString());
} catch (Exception e) {
LOGGER.printResponseToLogger(e.getMessage());
}
}
#Override
public void onFailure(Throwable ex) {
//TODO: Add real logging solution
LOGGER.printResponseToLogger(ex.getMessage());
}
});
} catch (Exception e) {
LOGGER.printResponseToLogger(e.getMessage());
}
}
}
Currently i'm thinking the solution to this issue would be for me to reuse the pools so that it doesn't increment to 2018 if that is possible but i have not found a way to do so.

try-catch-finally block in java

As per my understanding, I want to follow the best practice for releasing the resources at the end to prevent any connection leaks. Here is my code in HelperClass.
public static DynamoDB getDynamoDBConnection()
{
try
{
dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
}
catch(AmazonServiceException ase)
{
//ase.printStackTrace();
slf4jLogger.error(ase.getMessage());
slf4jLogger.error(ase.getStackTrace());
slf4jLogger.error(ase);
}
catch (Exception e)
{
slf4jLogger.error(e);
slf4jLogger.error(e.getStackTrace());
slf4jLogger.error(e.getMessage());
}
finally
{
dynamoDB.shutdown();
}
return dynamoDB;
}
My doubt is, since the finally block will be executed no matter what, will the dynamoDB returns empty connection because it will be closed in finally block and then execute the return statement? TIA.
Your understanding is correct. dynamoBD.shutdown() will always execute before return dynamoDB.
I'm not familiar with the framework you're working with, but I would probably organize the code as follows:
public static DynamoDB getDynamoDBConnection()
throws ApplicationSpecificException {
try {
return new DynamoDB(new AmazonDynamoDBClient(
new ProfileCredentialsProvider()));
} catch(AmazonServiceException ase) {
slf4jLogger.error(ase.getMessage());
slf4jLogger.error(ase.getStackTrace());
slf4jLogger.error(ase);
throw new ApplicationSpecificException("some good message", ase);
}
}
and use it as
DynamoDB con = null;
try {
con = getDynamoDBConnection();
// Do whatever you need to do with con
} catch (ApplicationSpecificException e) {
// deal with it gracefully
} finally {
if (con != null)
con.shutdown();
}
You could also create an AutoCloseable wrapper for your dynamoDB connection (that calls shutdown inside close) and do
try (DynamoDB con = getDynamoDBConnection()) {
// Do whatever you need to do with con
} catch (ApplicationSpecificException e) {
// deal with it gracefully
}
Yes,dynamoDB will return an empty connection as dynamoBD.shutdow() will be executed before return statement, Always.
Although I am not answering your question about the finally block being executed always (there are several answers to that question already), I would like to share some information about how DynamoDB clients are expected to be used.
The DynamoDB client is a thread-safe object and is intended to be shared between multiple threads - you can create a global one for your application and re-use the object where ever you need it. Generally, the client creation is managed by some sort of IoC container (Spring IoC container for example) and then provided by the container to whatever code needs it through dependency injection.
Underneath the hood, the DynamoDB client maintains a pool of HTTP connections for communicating the DynamoDB endpoint and uses connections from within this pool. The various parameters of the pool can be configured by passing an instance of the ClientConfiguration object when constructing the client. For example, one of the parameters is the maximum number of open HTTP connections allowed.
With the above understanding, I would say that since the DynamoDB client manages the lifecycle of HTTP connections, resource leaks shouldn't really be concern of code that uses the DynamoDB client.
How about we "imitate" the error and see what happens ? This is what I mean:
___Case 1___
try{
// dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
throw new AmazonServiceException("Whatever parameters required to instantiate this exception");
} catch(AmazonServiceException ase)
{
//ase.printStackTrace();
slf4jLogger.error(ase.getMessage());
slf4jLogger.error(ase.getStackTrace());
slf4jLogger.error(ase);
}
catch (Exception e)
{
slf4jLogger.error(e);
slf4jLogger.error(e.getStackTrace());
slf4jLogger.error(e.getMessage());
}
finally
{
//dynamoDB.shutdown();
slf4jLogger.info("Database gracefully shutdowned");
}
___Case 2___
try{
// dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
throw new Exception("Whatever parameters required to instantiate this exception");
} catch(AmazonServiceException ase)
{
//ase.printStackTrace();
slf4jLogger.error(ase.getMessage());
slf4jLogger.error(ase.getStackTrace());
slf4jLogger.error(ase);
}
catch (Exception e)
{
slf4jLogger.error(e);
slf4jLogger.error(e.getStackTrace());
slf4jLogger.error(e.getMessage());
}
finally
{
//dynamoDB.shutdown();
slf4jLogger.info("Database gracefully shutdowned");
}
These exercise could be a perfect place to use unit tests and more specifically mock tests. I suggest you to take a close look at JMockit, which will help you write such tests much more easily.

Using Thrift with Java, org.apache.thrift.TApplicationException unknown result

I am trying to write an RPC with Thrift, the client seems to be communicating to the server just fine, and the server creates a list to return to the client (proper format). But then the client somehow cannot recognize the packet as I get this error:
org.apache.thrift.TApplicationException: getEntityByIP failed: unknown result
This is what my thrift file looks like:
struct EntityLookupMessage{
1: list<i32> entityIDs;
}
service EntityJoinService {
list<i32> getEntityByIP(1:string IPval,2:i32 date);
}
And the ServerImpl is the following method:
public List<Integer> getEntityByIP(String IPval, int date) throws TException {
try{
System.out.println("Checking..."+IPval);
List<Integer> response=EntityJoinStandalone.getEntityByIP(entityLookup,IPval, date);
System.out.println(response);
return response;
}finally{
// TODO Auto-generated method stub
return null
}
Which is called by a client like so:
List<Integer> entity = client.getEntityByIP(IPval, date);
Any ideas why this is the case?
Cause
Thrift by design doesn't allow for null results. This is the code of the generated recv_Xxx() function:
public List<Integer> recv_getEntityByIP() throws org.apache.thrift.TException
{
getEntityByIP_result result = new getEntityByIP_result();
receiveBase(result, "getEntityByIP");
if (result.isSetSuccess()) {
return result.success;
}
throw new org.apache.thrift.TApplicationException(
org.apache.thrift.TApplicationException.MISSING_RESULT,
"getEntityByIP failed: unknown result");
}
You have to return a valid result, which is ...
a valid list, which may be empty, but must not be null
an exception thrown on the server
Solution
Remove the return null from your finally clause.
Best practice
Put the result into an object, similar to what you already did with the args:
struct EntityByIP_result {
1: list<i32> data;
}
This way you also leave room for further improvements down the road, you can add new fields to the struct at any time.

Categories