I am trying to test my #PreAuthorize tags that are placed on the methods in my Spring Controller. I am not getting any logging information as to the decisions being made by Spring on whether to allow or disallow a call. Currently I am being allowed into a method and I want to debug why I am being allowed even though I don't have the role.
I am using Spring Framework 3.2.3, Spring Security 3.1.4, Logback 1.0.13, Logback Spring 0.1.1.
Here is my logback file:
...
<appender name="MAIN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/logs/main_log.txt</file>
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>TRACE</level>
</filter>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %p | %c %M | %m%n</pattern>
</encoder>
<rollingPolicy>
<fileNamePattern>/logs/main_log.txt.%d</fileNamePattern>
</rollingPolicy>
</appender>
<logger name="org.springframework" level="TRACE"/>
<logger name="my.package" level="TRACE"/>
<root level="WARN">
<appender-ref="MAIN"/>
</root>
I have the listener set up properly in my web.xml file. I know this because I am getting log messages from the package my.package as well as WARN messages from 3rd party software.
Any ideas as to how I can see the decisions being made by the #PreAuthorize annotation?
Your configuration seeems fine, but Spring unfortunately uses commons logging. Follow the official documentation on how to use SLF4J (+ log4j or logback).
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/overview.html#overview-not-using-commons-logging
Just don't add commons-logging jar or if you use Maven exlude it like shown in the documentation. Then you need a bridge between commons-logging and SLF4J (jcl-over-slf4j.jar).
Cut out from my (working) configuration:
<logger name="org.springframework" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</logger>
pom.xml:
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.13</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.0.13</version>
<scope>runtime</scope>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
In order to use Pre-PostAuthorize annotations, it's necessary to enable their use in spring configuration, as they are off by default.
This is how to enable these annotations when using the global-method-security XML element (see here for further details):
<global-method-security pre-post-annotations="enabled"/>
Related
I am getting the following warning in spring mvc 5.2.8 when I configure log4j xml. The log messages are not printed in the console window.
log4j:WARN No appenders could be found for logger (com.mchange.v2.log.MLog).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
I have added the following to the pom.xml
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.13.3</version>
</dependency>
log4j2.xml in src folder
<configuration>
<appender name="log_console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<param name="Threshold" value="INFO"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="Log:%d [%t] %-5p %c - %m%n %L"/>
</layout>
</appender>
</configuration>
web.xml
<listener>
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>
Has someone faced this before? Can someone guide me how to solve this error?
I just want to send logs with ERROR level via email in my spring boot application using log4j2.
After reading infinite tutorials about this, im unable to reach this.
I have a Docker SMTP server in localhost, and here are my configuration files:
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Add Log4j2 Dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- Needed for SMTP appender -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
...
...
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="trace">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="%style{%d{ISO8601}}{black} %highlight{%-5level }[%style{%t}{bright,blue}] %style{%C}{bright,yellow}: %msg%n%throwable" />
</Console>
<SMTP name="MailAppender"
subject="error log"
to="test#monitor.com"
from="monitor#monitor.com"
smtpHost="localhost"
smtpPort="25"
bufferSize="10"
ignoreExceptions="false"
smtpDebug="true"
>
<ThresholdFilter level="ERROR" onMatch="ACCEPT"/>
<PatternLayout>
<pattern>%d %p [%C] [%t] %m%n</pattern>
</PatternLayout>
</SMTP>
</Appenders>
<Loggers>
<Root level="all">
<AppenderRef ref="MailAppender" level="debug" />
</Root>
</Loggers>
</Configuration>
application.yml
spring:
mail:
host: localhost
port: 25
auth: false
properties:
mail:
transport:
protocol: smtp
smtp:
auth: false
host: localhost
port: 25
With this configuration, log4j2 isnt able to send any mail. Aparently, log4j2 takes configuration correctly on startup:
2020-09-24 18:31:32,780 restartedMain DEBUG createAppender(Configuration(/XXX/target/classes/log4j2.xml), name="MailAppender", to="test#monitor.com", cc="null", bcc="null", from="monitor#monitor.com", replyTo="null", subject="error log", smtpProtocol="null", smtpHost="localhost", smtpPort="25", smtpUsername="null", smtpPassword="c0323768f8f5dc63ac2d877d8e65de66", smtpDebug="true", bufferSize="10", PatternLayout(%d %p [%C] [%t] %m%n), ThresholdFilter(ERROR), ignoreExceptions="false")
but then it cannot send any email.
The funniest thing is that I can use spring mail to send mails (using JavaMailSender API) with same configuration, so I think that there is a problem with log4j2 configuration. Maybe log4j2 overrides mail configuration for any reason?
Could anyone help me?
Ok, I finally solved it. It have been working everytime, but it doesnt recognizes my application logger, so it only works with spring framework log names, for example: org.springframework.boot
I solved adding a new logger referencing my SMTPAppender:
<Logger name="com.myapp" level="all" additivity="false">
<AppenderRef ref="AsyncMailer" level="debug" />
</Logger>
And on a log.error("XXX"), it sends a mail with the log info.
Couldn't find any good answer why slf4j logging not working with spring 4. Thanks to this post I've made particularly all work, but the author didn't mention that:
The mandatory logging dependency in Spring is the Jakarta Commons Logging API (JCL)
(http://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/htmlsingle/).
It means that if we want slf4j to work WE MUST EXCLUDE commons-logging from our classpath (or pom.xml if using maven). While using maven spring-core automatically picks commons-logging. (I understood this when executed the command "mvn dependency:tree").
STEPS TO REPRODUCE:
Exclude commons-logging from spring-core
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
Add to the pom.xml next dependencies:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.19</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.19</version>
</dependency>
Create log4j2.xml file like this (if you want log4j2 logging through slf4j).
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="CONSOLE" />
</Root>
<logger level="info" additivity="false" name="org.springframework.security">
<AppenderRef ref="CONSOLE" />
</logger>
<logger level="info" additivity="false" name="org.springframework.web">
<AppenderRef ref="CONSOLE" />
</logger>
<logger level="warn" additivity="false" name="controllers">
<AppenderRef ref="CONSOLE" />
</logger>
</Loggers>
</Configuration>
write log messages in your classes:
private final Logger logger =LoggerFactory.getLogger(this.getClass());
logger.debug("This is a debug message");
logger.info("This is an info message");
You do not need to exclude commons-logging. If you use log4j-jcl instead of jcl-over-slf4j the Spring logging will be routed to log4j directly instead of going through slf4j.
Now, thanx to #rgoers my logging part of pom.xml looks like:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.19</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jcl</artifactId>
<version>2.5</version>
</dependency>
I am using slf4j, logback for logging in my Spring application. I have configured to exclude common-logging and add the jcl-over-slf4j bridge.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.3</version>
</dependency>
My logback.xml looks like the following:
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
<logger name="com.my" level="DEBUG" />
The problem is when running maven builds, classes from spring always prints in DEBUG level which pollutes the console with verbose information. This doesn't happen when running the app with Tomcat though.
Also, if I extend a class of Spring, e.g. HttpSessionRequestCache, logging statements from the Spring classes are executed, as if it get the level from the child class! This does happen when running with Tomcat.
How to make Maven honor the logback.xml configuration?
I know this has been asked before but none of the answers has worked for me yet. I get the error:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
I've allready tryed to use:
Only slf4j-api
slf4j-api and log4j
slf4j-api, jcl-over-slf4j, log4j
Only slf4j-log4j12
slf4j-log4j12 and log4j
Only logback-classic
logback-classic and logback-core
slf4j-api, logback-classic and logback-core
log4j-api 2, log4j-core 2, log4j-slf4j-impl
log4j-over-slf4j, jul-to-slf4j, logback-classic
slf4j-api, logback-classic
For each one I've tried with the tutorial/answer version and the latest (mvn versions:use-latest-version)
Since there are some answers arround there that tells you can only have one of those libraries on your classpath I remark that I've already tryed em.
Also I've used a log4j.properties inside src/main/resources/ like this one:
# Set root logger level and appender name.
log4j.rootLogger = ALL, file
# Specify appenders.
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.file = org.apache.log4j.DailyRollingFileAppender
# Configure console appender.
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %d{ABSOLUTE} [%t] %-5p %m%n
# Configure file appender.
log4j.appender.file.File = /webapp/logs/web.log
log4j.appender.file.DatePattern = '.'yyyy-MM-dd
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %d{ABSOLUTE} [%t] %-5p %m%n
And a logback.xml at the same place:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>silkroad.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.base22" level="ALL"/>
<root level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>
This is the code I've tried out:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Test {
static Logger log = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) {
log.debug("Testing the log");
}
}
Appart from the loggin dependences I use:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
I've followed several tutorials (12~15) using different ways of geting the log facade working, including the ones on theyr sites without success.
This configuration works for a project I have. I am using log4j 1, a standard log4j.xml file. I also had to exclude commons-logging from any dependency that includes it, e.g. spring-core as shown.
<properties>
<spring.version>4.0.0.RELEASE</spring.version>
<log4j.version>1.2.17</log4j.version>
<slf4j.version>1.7.5</slf4j.version>
</properties>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
....
</dependencies>