I have successfully installed OWasp CSRFGuard in my Java Application.
My CSRFGuard.Properties file contains the following:
# Logger
#
# The logger property (org.owasp.csrfguard.Logger) defines the qualified class name of
# the object responsible for processing all log messages produced by CSRFGuard. The default
# CSRFGuard logger is org.owasp.csrfguard.log.ConsoleLogger. This class logs all messages
# to System.out which JavaEE application servers redirect to a vendor specific log file.
# Developers can customize the logging behavior of CSRFGuard by implementing the
# org.owasp.csrfguard.log.ILogger interface and setting the logger property to the new
# logger's qualified class name. The following configuration snippet instructs OWASP CSRFGuard
# to capture all log messages to the console:
#
# org.owasp.csrfguard.Logger=org.owasp.csrfguard.log.ConsoleLogger
org.owasp.csrfguard.Logger=org.owasp.csrfguard.log.JavaLogger
I can see the different logging levels from https://www.javatips.net/api/OWASP-CSRFGuard-master/csrfguard/src/main/java/org/owasp/csrfguard/log/JavaLogger.java
LOGGER.log(Level.FINEST, exception.getLocalizedMessage(), exception);
break;
case Debug:
LOGGER.log(Level.FINE, exception.getLocalizedMessage(), exception);
break;
case Info:
LOGGER.log(Level.INFO, exception.getLocalizedMessage(), exception);
break;
case Warning:
LOGGER.log(Level.WARNING, exception.getLocalizedMessage(), exception);
break;
case Error:
LOGGER.log(Level.WARNING, exception.getLocalizedMessage(), exception);
break;
case Fatal:
LOGGER.log(Level.SEVERE
How can I change the logging level in CSRFGuard.Properties to show only Level.WARNING
At the moment, every request is analyzed and logged.
INFO: CsrfGuard analyzing request example.com/examplepage.jsp
Replace the following line in CSRFGuard.Properties
org.owasp.csrfguard.Logger=org.owasp.csrfguard.log.JavaLogger
with
org.owasp.csrfguard.Logger=com.myPackage.MyLogger
And add a new class as below (based on this code), setting your required log level in the MyLogger() constructor (in the example below I set the minimum log level to Level.WARNING)
package com.myPackage
import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.csrfguard.log.LogLevel;
public class MyLogger implements org.owasp.csrfguard.log.ILogger {
private static final long serialVersionUID = 1L;
private final static Logger LOGGER = Logger.getLogger("Owasp.CsrfGuard");
public MyLogger() {
LOGGER.setLevel(Level.WARNING);
}
#Override
public void log(String msg) {
LOGGER.info(msg.replaceAll("(\\r|\\n)", ""));
}
#Override
public void log(LogLevel level, String msg) {
// Remove CR and LF characters to prevent CRLF injection
String sanitizedMsg = msg.replaceAll("(\\r|\\n)", "");
switch(level) {
case Trace:
LOGGER.finest(sanitizedMsg);
break;
case Debug:
LOGGER.fine(sanitizedMsg);
break;
case Info:
LOGGER.info(sanitizedMsg);
break;
case Warning:
LOGGER.warning(sanitizedMsg);
break;
case Error:
LOGGER.warning(sanitizedMsg);
break;
case Fatal:
LOGGER.severe(sanitizedMsg);
break;
default:
throw new RuntimeException("unsupported log level " + level);
}
}
#Override
public void log(Exception exception) {
LOGGER.log(Level.WARNING, exception.getLocalizedMessage(), exception);
}
#Override
public void log(LogLevel level, Exception exception) {
switch(level) {
case Trace:
LOGGER.log(Level.FINEST, exception.getLocalizedMessage(), exception);
break;
case Debug:
LOGGER.log(Level.FINE, exception.getLocalizedMessage(), exception);
break;
case Info:
LOGGER.log(Level.INFO, exception.getLocalizedMessage(), exception);
break;
case Warning:
LOGGER.log(Level.WARNING, exception.getLocalizedMessage(), exception);
break;
case Error:
LOGGER.log(Level.WARNING, exception.getLocalizedMessage(), exception);
break;
case Fatal:
LOGGER.log(Level.SEVERE, exception.getLocalizedMessage(), exception);
break;
default:
throw new RuntimeException("unsupported log level " + level);
}
}
}
Related
I have a custom filter that authenticates every request before calling the actual API using Spring Cloud Gateway. Is there any way in Spring Cloud to handle exceptions centrally same as the Spring provide #ControllerAdvice? I want to handle exceptions globally and return custom error responses from the gateway.
Once an exception is thrown from your authentication filter, you can customize the error response by overriding the DefaultErrorAttributes class.
#Component
public class GlobalErrorAttributes extends DefaultErrorAttributes {
private static final Logger logger = LoggerFactory.getLogger(GlobalErrorAttributes.class);
public GlobalErrorAttributes() {
}
public GlobalErrorAttributes(boolean includeException) {
super(includeException);
}
#Override
public Map<String, Object> getErrorAttributes(ServerRequest request,
boolean includeStackTrace) {
Throwable error = this.getError(request);
logger.error("Error occured", error);
MergedAnnotation<ResponseStatus> responseStatusAnnotation = MergedAnnotations
.from(error.getClass(), MergedAnnotations.SearchStrategy.TYPE_HIERARCHY).get(ResponseStatus.class);
HttpStatus errorStatus = findHttpStatus(error, responseStatusAnnotation);
logger.info("errorStatus: {}", errorStatus);
Map<String, Object> map = super.getErrorAttributes(request, includeStackTrace);
String errorCode = getErrorCode(map, errorStatus);
map.remove("timestamp");
map.remove("path");
map.remove("error");
map.remove("requestId");
map.put("errorCode", errorCode);
return map;
}
private HttpStatus findHttpStatus(Throwable error, MergedAnnotation<ResponseStatus> responseStatusAnnotation) {
if (error instanceof ResponseStatusException) {
return ((ResponseStatusException) error).getStatus();
}
return responseStatusAnnotation.getValue("code", HttpStatus.class).orElse(INTERNAL_SERVER_ERROR);
}
private String getErrorCode(Map<String, Object> map, HttpStatus errorStatus) {
String errorCode;
switch (errorStatus) {
case UNAUTHORIZED:
errorCode = "401 UnAuthorized";
break;
case NOT_FOUND:
logger.error("The url:{} is not found", map.get("path"));
errorCode = "404 Not Found";
map.put(MESSAGE, "NOT FOUND");
break;
case METHOD_NOT_ALLOWED:
logger.error("Invalid HTTP Method type for the url: {}", map.get("path"));
errorCode = "405 Method Not Allowed";
break;
default:
logger.error("Unexpected error happened");
logger.error("errorstatus is : {}", errorStatus);
errorCode = "500 Internal Server Error";
map.put(MESSAGE, "Unexpected Error");
}
return errorCode;
}
}
The output will be something like below:
{
"status": 401,
"message": "Invalid Access Token",
"error_code": "401 UnAuthorized"
}
I have a Windows Service which basically wraps a task:
public partial class Service : ServiceBase
{
private Task task;
private CancellationTokenSource cancelToken;
public Service()
{
InitializeComponent();
this.task = null;
this.cancelToken = null;
}
protected override void OnStart(string[] args)
{
var svc = new MyServiceTask();
this.cancelToken = new CancellationTokenSource();
this.task = svc.RunAsync(cancelToken.Token);
this.task.ContinueWith(t => this.OnUnhandledException(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
}
protected override void OnStop()
{
if (this.task != null)
{
this.cancelToken.Cancel();
this.task.Wait();
}
}
private void OnUnhandledException(Exception ex)
{
this.EventLog.WriteEntry(string.Format("Unhandled exception: {0}", ex), EventLogEntryType.Error);
this.task = null;
this.Stop();
}
}
As you can see, the service can catch unhandled exceptions. If this happens, the exception is logged and the service is stopped. This has the effect of writing two messages to the event log - one error stating there was an unhandled exception, and another stating that the service was successfully stopped.
This may sound minor, but I'm hoping to be able to suppress the 'successfully stopped' message. I find it misleading - it suggests that the service stopping was a normal occurrence. Is there another way I can force the service to stop itself without this message being logged?
I'm using GWT and Resty for my web app.
I need to treat two exceptions as special cases and pass additional information to the client. These previously were handled by the Resty calls onFailure() method, as follows:
getClientFactory().getRequest().restyMethod(id,
new MethodRecipient<DataDTO>() {
#Override
public void onSuccess(Method method, DataDTO response) {
// do stuff
}
#Override
public void onFailure(Method method, Throwable ex) {
if (ex.getMessage().endsWith("exception message 1")) {
getClientFactory().getAppController().showRestFatalError("Message 1", "Title 1", errorMsg);
} else if (ex.getMessage().endsWith("exception message 2")) {
getClientFactory().getAppController().showRestFatalError("Message 2", "Title 2", errorMsg);
} else {
// else fall back to a friendly but vague "something else went wrong"
getClientFactory().getAppController().showRestFatalError("Unexpected error", "Unexpected Error", errorMsg);
}
}
});
To catch and log all exceptions before they get to the client, I've implemented a custom Spring MVC HandlerExceptionResolver as follows:
I have a custom HandlerExceptionResolver for logging controller errors as below:
#Component
public class LoggingHandlerExceptionResolver extends AbstractHandlerExceptionResolver {
private final Logger logger = LoggerFactory.getLogger(LoggingHandlerExceptionResolver.class);
#Override
public ModelAndView doResolveException(HttpServletRequest aReq, HttpServletResponse aRes, Object aHandler, Exception ex) {
logger.error("Server exception thrown", ex);
return null; // trigger other HandlerExceptionResolvers
}
}
When using the HandlerExceptionResolver, only status code 500 gets passed to the client. How do I get the two special cases to be recognized by the onFailure() method?
This is my first time that I am using RMI, basically I manage to run the following RMI example locally on my PC but not via two separate Linux machines.
The server interface:
public interface PowerService extends Remote{
public BigInteger square ( int number )
throws RemoteException;
public BigInteger power ( int num1, int num2)
throws RemoteException;
}
The server:
public class PowerServiceServer extends UnicastRemoteObject implements
PowerService {
public PowerServiceServer() throws RemoteException {
super();
}
public BigInteger square(int number) throws RemoteException {
imp .....
return (bi);
}
public BigInteger power(int num1, int num2) throws RemoteException {
imp .....
return bi;
}
public static void main(String[] args) throws Exception {
PowerServiceServer svr = new PowerServiceServer();
// ... and bind it with the RMI Registry
Naming.bind("PowerService", svr);
System.out.println("Service bound....");
}
}
The client:
public class PowerServiceClient {
public static void main(String args[]) throws Exception {
// Call registry for PowerService
PowerService service = (PowerService) Naming.lookup("rmi://" + args[0]
+ "/PowerService");
DataInputStream din = new DataInputStream(System.in);
for (;;) {
System.out.println("1 - Calculate square");
System.out.println("2 - Calculate power");
System.out.println("3 - Exit");
System.out.println();
System.out.print("Choice : ");
String line = din.readLine();
Integer choice = new Integer(line);
int value = choice.intValue();
switch (value) {
case 1:
// Call remote method
....................
break;
case 2:
// Call remote method
....................
break;
case 3:
System.exit(0);
default:
System.out.println("Invalid option");
break;
}
}
}
and the client interfaces is the same like the server
This is what I did in order to run the rmi example:
1) On the server side I created the stub
2) Run rmiregisrty
3) Run the server
4) I copy the stub from the server side to the client side in to the same package
5) Run the client
After running the client I got the following error message:
Exception in thread "main" java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:
java.net.ConnectException: Connection refused
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:601)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:110)
at compute.PowerServiceServer_Stub.square(Unknown Source)
is possible that due to some firewall I can’t connect or perhaps I am doing something wrong ??
Thanks
This is the problem addressed by java.rmi.server.hostname. See item A.1 in the RMI FAQ. You need to either fix the /etc/hosts misconfiguration that causes it, or set the system property java.rmi.server.hostname in the server JVM to the correct IP address of the server, before exporting any remote objects.
I'm trying to create a simple DB connection using JPA.
It works fine but when I try to Throw an Exception to the client I get the error:
[ERROR] [browsereditor] - Line 210: No source code is available for type javax.persistence.EntityExistsException; did you forget to inherit a required module?
[ERROR] [browsereditor] - Line 212: No source code is available for type javax.persistence.EntityNotFoundException; did you forget to inherit a required module?
I get no error in development mode and it compiles fine, but when the app module is loaded there is where I get the error.
I have the required imports in server/Composer and client/Presenter classes
import javax.persistence.EntityExistsException;
import javax.persistence.EntityNotFoundException;
I also added the following jars to the classpath and build path:
javax.persistence.jar
jpa-annotations-source.jar (http://code.google.com/p/google-web-toolkit/issues/detail?id=1830#c14)
I also tried adding to gwt.xml
<source path='client'/>
<source path='shared'/>
<source path='server'/>
Any ideas on how to tell eclipse where to find the source code??
Thanks
Here is the code:
//Create composer from Composer.class in server
public static Composer createComposer(String name)
throws EntityExistsException {
Composer comp = new Composer();
comp.setName(name);
comp.setId(1);
EntityManager entityManager = entityManager();
entityManager.getTransaction().begin();
entityManager.persist(comp);
entityManager.getTransaction().commit();
entityManager.close();
return comp;
}
///fire Request from createComposer(above) in Presenter.class
req.fire(new Receiver<ComposerProxy>() {
public void onSuccess(ComposerProxy arg0) {
ComposerProxy comp;
comp = arg0;
}
public void onFailure(Throwable caught)
throws Throwable {
// Convenient way to find out which exception
// was thrown.
try {
throw caught;
} catch (EntityExistsException e) {
} catch (EntityNotFoundException e) {
}
}});
}});
[ERROR] [browsereditor] - Line 210: No source code is available for type javax.persistence.EntityExistsException; did you forget to inherit a required module?
[ERROR] [browsereditor] - Line 212: No source code is available for type javax.persistence.EntityNotFoundException; did you forget to inherit a required module?
You can't use types such as EntityExistsException or EntityNotFoundException in client-side GWT code at all.
These are plain Java classes and GWT don't know how to translate them to JavaScript.
You can only use very limited part of external libraries in your client-side code. These libraries (like Visualisation for example) are designed and prepared specifically for client-side and require inheriting their GWT module in your application's module.
I think that what you really want to do is something like that:
public void onFailure(ServerFailure failure) throws Throwable {
if(failure.getExceptionType().equals("javax.persistence.EntityExistsException")){
...
}else if(failure.getExceptionType().equals("javax.persistence.EntityNotFoundException")){
...
}
}
Because you can read type of server-side exception as String, see Javadoc for Receiver and ServerFailure.
Thanks Piotr for your help.
Here is the code for what I finally did:
Code in the client
req.fire(new Receiver<ComposerProxy>() {
public void onSuccess(ComposerProxy arg0) {
ComposerProxy comp;
comp = arg0;
}
public void onFailure(ServerFailure failure) {
serverError.getServerError(failure,
"onAddButtonClicked");
}
});
I created a class to handle the errors
public class ServerError {
public ServerError() {
}
public void getServerError(ServerFailure failure, String message) {
// Duplicate Key Error
if (failure.getMessage().contains(
"IntegrityConstraintViolationException")) {
Window.alert("Duplicate Key " + message);
return;
}
// Connection Error
if (failure.getMessage().contains("NonTransientConnectionException")) {
Window.alert("Connection error ");
return;
}
// TimeOut Error
if (failure.getMessage().contains("TimeoutException")) {
Window.alert("Timeout Error" + message);
return;
}
// Other Error
else {
Window.alert("Duplicate Key " + message);
return;
}
}
}
Service in the server
public static Composer createComposer(String name) throws Throwable {
EntityManager entityManager = entityManager();
Composer comp = new Composer();
try {
comp.setName(name);
comp.setId(1);
entityManager.getTransaction().begin();
entityManager.persist(comp);
entityManager.getTransaction().commit();
} catch (Exception e) {
log.error("Error in Composer::createComposer( " + name + ") //"
+ e.toString());
throw e;
} finally {
entityManager.close();
}
return comp;
}
One problem I found is that the variable 'ServerFailure failure'only contains info in the failure.message; all the other variables are null.