Springboot Actuator의 10: actuator의 audit 패키지

47073 단어
앞의 이 문장은 우리가 org를 분석해 봅시다.springframework.boot.actuate.security,org.springframework.boot.actuate.audit의 코드, 이 두 패키지의 클래스는spring 보안 이벤트를 처리합니다.클래스는 다음과 같습니다.
 

2. 원본 코드 해석


2.1 AuditEvent 이벤트 클래스


Audit Event – > 1개의 값 대상 -> 1개의audit 이벤트를 대표합니다: 특정한 시간, 1개의 특정한 사용자 또는 에이전트에서 1개의 특정한 유형의 동작을 실시합니다.Audit Event는 Audit Event에 관한 세부 사항을 기록했다.
클래스에는 다음과 같은 메모가 있습니다.
@JsonInclude(Include.NON_EMPTY)

이 클래스가 비어 있거나 null인 속성은 서열화되지 않습니다.
클래스 필드는 다음과 같습니다.
private final Date timestamp;

//   
private final String principal;

private final String type;

private final Map data;

 

2.2 AuditApplication Event 이벤트 클래스


AuditApplication Event – > 패키지 AuditEvent.코드는 다음과 같습니다.
public class AuditApplicationEvent extends ApplicationEvent {

    private final AuditEvent auditEvent;


    public AuditApplicationEvent(String principal, String type,
            Map data) {
        this(new AuditEvent(principal, type, data));
    }

    AuditApplicationEvent(String principal, String type, String... data) {
        this(new AuditEvent(principal, type, data));
    }


    public AuditApplicationEvent(Date timestamp, String principal, String type,
            Map data) {
        this(new AuditEvent(timestamp, principal, type, data));
    }


    public AuditApplicationEvent(AuditEvent auditEvent) {
        super(auditEvent);
        Assert.notNull(auditEvent, "AuditEvent must not be null");
        this.auditEvent = auditEvent;
    }


    public AuditEvent getAuditEvent() {
        return this.auditEvent;
    }

}

 

2.3、AbstractAuditListener


AbstractAuditListener – > AuditApplication Event 이벤트의 추상적인 클래스를 처리합니다.코드는 다음과 같습니다.
public abstract class AbstractAuditListener
        implements ApplicationListener {

    @Override
    public void onApplicationEvent(AuditApplicationEvent event) {
        onAuditEvent(event.getAuditEvent());
    }

    protected abstract void onAuditEvent(AuditEvent event);

}

 

2.4、AuditEventRepository


Audit Event Repository –>Audit Event에 대한dao 실현.다음과 같은 네 가지 방법이 설명되어 있습니다.
//     
void add(AuditEvent event);

//          AuditEvent
List find(Date after);

//      Date principal(  )     AuditEvent
List find(String principal, Date after);

//     date,principal,type       AuditEvent
List find(String principal, Date after, String type);

 

2.5、InMemoryAuditEventRepository


Memory Audit Event Repository –> Audit Event Repository 인터페이스의 유일한 실현.
클래스 필드는 다음과 같습니다.
// AuditEvent         
private static final int DEFAULT_CAPACITY = 4000;

//    events         
private final Object monitor = new Object();

/**
* Circular buffer of the event with tail pointing to the last element.
*     
*/
private AuditEvent[] events;

//   1      
private volatile int tail = -1;

작성자는 다음과 같습니다.
public InMemoryAuditEventRepository() {
   this(DEFAULT_CAPACITY);
}

public InMemoryAuditEventRepository(int capacity) {
   this.events = new AuditEvent[capacity];
}

AuditEventRepository 의 방법은 다음과 같습니다.
    @Override
    public void add(AuditEvent event) {
        Assert.notNull(event, "AuditEvent must not be null");
        synchronized (this.monitor) {
            this.tail = (this.tail + 1) % this.events.length;
            this.events[this.tail] = event;
        }
    }

    @Override
    public List find(Date after) {
        return find(null, after, null);
    }

    @Override
    public List find(String principal, Date after) {
        return find(principal, after, null);
    }
    //              
    @Override
    public List find(String principal, Date after, String type) {
        LinkedList events = new LinkedList();
        synchronized (this.monitor) {
        // 1.   events
        for (int i = 0; i < this.events.length; i++) {
            // 1.1      AuditEvent
            AuditEvent event = resolveTailEvent(i);
            // 1.2   AuditEvent    null          ,    events 
            if (event != null && isMatch(principal, after, type, event)) {
                events.addFirst(event);
            }
        }
    }
        // 2.      
        return events;
    }

    //         
    private boolean isMatch(String principal, Date after, String type, AuditEvent event) {
        boolean match = true;
        match = match && (principal == null || event.getPrincipal().equals(principal));
        match = match && (after == null || event.getTimestamp().compareTo(after) >= 0);
        match = match && (type == null || event.getType().equals(type));
        return match;
    }
    
    //     AuditEvent
    private AuditEvent resolveTailEvent(int offset) {
        int index = ((this.tail + this.events.length - offset) % this.events.length);
        return this.events[index];
    }

 
결과 세트로 돌아가기
여기에는 두 가지 질문이 있습니다.
1. 앞에서 말했듯이 이벤트에 접근할 때 잠금을 추가해야 하는데 왜 ResolveTail Event 방법은 잠금을 추가하지 않았습니까?
이유는 다음과 같다.resolveTail Event의 호출점은 하나뿐이다.find(String Date,String)에 있고 이 방법에는 이미 자물쇠가 설치되어 있기 때문에 이 방법은 자물쇠를 추가할 필요가 없다.
2. resolveTail Event 방법에 자물쇠를 채워도 됩니까
답:네,synchronized는 다시 들어갈 수 있기 때문입니다.하지만 추천하지 않습니다. 더하면 성능 손실이 발생합니다.
이 방법의 실현 원리에 관해서 우리는 그래도 예를 드는 것이 비교적 좋다.배열 길이가 3개라고 가정하면 다음과 같이 배열이 가득 채워집니다.
[0,1,2]
이제 tail = 2, 그리고 3을 계속 넣으면 배열은 다음과 같습니다.
[3,1,2], 이때tail=0.그리고 우리는find를 호출합니다.이 메서드에서 resolveTailEvent가 호출됩니다.
첫 번째 전송이 0이면 index=(0+3-0)%3=0, 획득한 것이 바로 3.두 번째로 들어온 것이 1이면 index=(0+3-1)%3=2로 얻은 것이 바로 2.3번째 들어온 것이 2이면 index=(0+3-2)%3=1이고 획득한 것이 바로 1.따라서find(String, Date, String)가 얻은 결과는 추가된 순서에 따라 역순으로 되돌아온다.
자동 어셈블:
AuditAutoConfiguration 클래스 내의 static AuditEvent Repository Configuration 클래스에 설명된 코드는 다음과 같습니다.
@ConditionalOnMissingBean(AuditEventRepository.class)
protected static class AuditEventRepositoryConfiguration {

    @Bean
    public InMemoryAuditEventRepository auditEventRepository() throws Exception {
        return new InMemoryAuditEventRepository();
    }

}

 
beanFactory에Audit Event Repository 유형의 bean이 존재하지 않을 때 적용됩니다.ID 1개는 audit Event Repository, InMemory Audit Event Repository 유형은 bean.

2.6、AuditListener


AuditListener –> AbstractAuditListener의 기본 구현AuditApplication Event 이벤트를 감청하여AuditEvent Repository에 저장합니다.코드는 다음과 같습니다.
public class AuditListener extends AbstractAuditListener {

    private static final Log logger = LogFactory.getLog(AuditListener.class);

    private final AuditEventRepository auditEventRepository;

    public AuditListener(AuditEventRepository auditEventRepository) {
        this.auditEventRepository = auditEventRepository;
    }

    @Override
    protected void onAuditEvent(AuditEvent event) {
        if (logger.isDebugEnabled()) {
            logger.debug(event);
        }
        this.auditEventRepository.add(event);
    }

}

 
AuditApplication Event를 감청할 때, 봉인된 Audit Event를 Audit Event Repository에 직접 추가합니다.그래도 쉬워요.
자동 어셈블은 다음과 같습니다.
AuditAutoConfiguration에서 다음과 같은 코드로 선언되었습니다.
    @Bean
    @ConditionalOnMissingBean(AbstractAuditListener.class)
    public AuditListener auditListener() throws Exception {
        return new AuditListener(this.auditEventRepository);
    }

@Bean –> 등록 ID 1개는auditListener, 유형은AuditListener의bean@ConditionalOnMissingBean(AbstractAuditListener.class) -> BeanFactory에 AbstractAuditListener 유형의 bean이 존재하지 않을 때 적용됩니다.
AuditListener에 InMemory Audit Event Repository가 주입되어 있음을 주의하십시오

2.7AbstractAuthenticationAuditListener


Abstract Authentication Audit Listener – > Spring Security Abstract Authentication Event(인증 이벤트)를 Audit Event의 추상적인 Application Listener 기류로 변환하는 것을 폭로합니다.
코드는 다음과 같습니다.
public abstract class AbstractAuthenticationAuditListener implements
    ApplicationListener, ApplicationEventPublisherAware {

    private ApplicationEventPublisher publisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    protected ApplicationEventPublisher getPublisher() {
        return this.publisher;
    }

    protected void publish(AuditEvent event) {
        if (getPublisher() != null) {
            getPublisher().publishEvent(new AuditApplicationEvent(event));
        }
    }
}

 

2.8、AuthenticationAuditListener


AuthenticationAuditListener의 기본 구현 필드는 다음과 같습니다.
//    AuthenticationSuccessEvent      AuditEvent  type
public static final String AUTHENTICATION_SUCCESS = "AUTHENTICATION_SUCCESS";

//    AbstractAuthenticationFailureEvent      AuditEvent  type
public static final String AUTHENTICATION_FAILURE = "AUTHENTICATION_FAILURE";

//    AuthenticationSwitchUserEvent      AuditEvent  type
public static final String AUTHENTICATION_SWITCH = "AUTHENTICATION_SWITCH";

private static final String WEB_LISTENER_CHECK_CLASS = "org.springframework.security.web.authentication.switchuser.AuthenticationSwitchUserEvent";

private WebAuditListener webListener = maybeCreateWebListener();

//     spring-boot-starter-security   ,           org.springframework.security.web.authentication.switchuser.AuthenticationSwitchUserEvent
//      WebAuditListener
private static WebAuditListener maybeCreateWebListener() {
if (ClassUtils.isPresent(WEB_LISTENER_CHECK_CLASS, null)) {
return new WebAuditListener();
}
return null;
}

 
onApplicationEvent 방법은 다음과 같습니다.
public void onApplicationEvent(AbstractAuthenticationEvent event) {
    // 1.       ,
    if (event instanceof AbstractAuthenticationFailureEvent) {
        onAuthenticationFailureEvent((AbstractAuthenticationFailureEvent) event);
    }
    // 2.  webListener   null.      AuthenticationSwitchUserEvent
    else if (this.webListener != null && this.webListener.accepts(event)) {
        this.webListener.process(this, event);
    }
    // 3.    AuthenticationSuccessEvent
    else if (event instanceof AuthenticationSuccessEvent) {
        onAuthenticationSuccessEvent((AuthenticationSuccessEvent) event);
    }
}

1. 검증이 실패하면(Abstract Authentication Failure Event) Audit Event 이벤트를 보내고 type은 AUTHENTICATIONFAILURE.코드는 다음과 같습니다.
private void onAuthenticationFailureEvent(AbstractAuthenticationFailureEvent event) {
    Map data = new HashMap();
    data.put("type", event.getException().getClass().getName());
    data.put("message", event.getException().getMessage());
    if (event.getAuthentication().getDetails() != null) {
        data.put("details", event.getAuthentication().getDetails());
    }
    publish(new AuditEvent(event.getAuthentication().getName(),
            AUTHENTICATION_FAILURE, data));
}

만약 웹리스트가 null과 같지 않다면.또한 이 이벤트가 AuthenticationSwitchUser Event이면 AuditEvent 이벤트를 보내고 type은 AUTHENTICATIONSWITCH.코드는 다음과 같습니다.
public void process(AuthenticationAuditListener listener,
        AbstractAuthenticationEvent input) {
    if (listener != null) {
        AuthenticationSwitchUserEvent event = (AuthenticationSwitchUserEvent) input;
        Map data = new HashMap();
        if (event.getAuthentication().getDetails() != null) {
            data.put("details", event.getAuthentication().getDetails());
        }
        data.put("target", event.getTargetUser().getUsername());
        listener.publish(new AuditEvent(event.getAuthentication().getName(),
                AUTHENTICATION_SWITCH, data));
    }

}

3、AuthenticationSuccess Event이면 Audit Event 이벤트를 보내고 type은 AUTHENTICATIONSUCCESS.코드는 다음과 같습니다.
private void onAuthenticationSuccessEvent(AuthenticationSuccessEvent event) {
    Map data = new HashMap();
    if (event.getAuthentication().getDetails() != null) {
        data.put("details", event.getAuthentication().getDetails());
    }
    publish(new AuditEvent(event.getAuthentication().getName(),
            AUTHENTICATION_SUCCESS, data));
}

 
자동 어셈블:
AuditAutoConfiguration에서 다음과 같은 코드로 선언되었습니다.
@Bean
@ConditionalOnClass(name = "org.springframework.security.authentication.event.AbstractAuthenticationEvent")
@ConditionalOnMissingBean(AbstractAuthenticationAuditListener.class)
public AuthenticationAuditListener authenticationAuditListener() throws Exception {
    return new AuthenticationAuditListener();
}

1. @Bean –> 1개의 id를 authenticationAuditListener, AuthenticationAuditListener의 bean으로 등록
2. @Conditional Onclass(name = "org.springframework.security.authentication.event.Abstract Authentication Event") -> 현재 클래스 경로에 org가 존재하는 경우.springframework.security.authentication.event.Abstract Authentication Event 시 효력이 발생합니다 3, @Conditional Onmissing Bean(Abstract Authentication Audit Listener.class) ->bean Factory에 Abstract Authentication Audit Listener 유형의 bean이 존재하지 않을 때 효력이 발생합니다.

2.9、AbstractAuthorizationAuditListener


Abstract Authorization Audit Listener – > Abstract Authorization Event(권한 수여 이벤트)가 Audit Event의 추상적인 Application Listener 기류로 노출된 1개코드는 다음과 같습니다.
public abstract class AbstractAuthorizationAuditListener implements
        ApplicationListener, ApplicationEventPublisherAware {

    private ApplicationEventPublisher publisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    protected ApplicationEventPublisher getPublisher() {
        return this.publisher;
    }

    protected void publish(AuditEvent event) {
        if (getPublisher() != null) {
            getPublisher().publishEvent(new AuditApplicationEvent(event));
        }
    }

}

 

2.10、AuthorizationAuditListener


AuthorizationAuditListener – > AbstractAuthorizationAuditListener의 기본 구현 필드는 다음과 같습니다.
//   AuthorizationFailureEvent      AuditEvent   
public static final String AUTHORIZATION_FAILURE = "AUTHORIZATION_FAILURE";

onApplicationEvent 코드는 다음과 같습니다.
public void onApplicationEvent(AbstractAuthorizationEvent event) {
    // 1.    AuthenticationCredentialsNotFoundEvent  ,   AuditEvent  ,type AUTHENTICATION_FAILURE
    if (event instanceof AuthenticationCredentialsNotFoundEvent) {
        onAuthenticationCredentialsNotFoundEvent(
                (AuthenticationCredentialsNotFoundEvent) event);
    }
    // 2.    AuthorizationFailureEvent  ,   AuditEvent  ,type AUTHORIZATION_FAILURE
    else if (event instanceof AuthorizationFailureEvent) {
        onAuthorizationFailureEvent((AuthorizationFailureEvent) event);
    }
}

 
1、AuthenticationCredentialsNotFoundEvent 이벤트인 경우 AuditEvent 이벤트를 보내고, type은 AUTHENTICATIONFAILURE.코드는 다음과 같습니다.
private void onAuthenticationCredentialsNotFoundEvent(
        AuthenticationCredentialsNotFoundEvent event) {
    Map data = new HashMap();
    data.put("type", event.getCredentialsNotFoundException().getClass().getName());
    data.put("message", event.getCredentialsNotFoundException().getMessage());
    publish(new AuditEvent("",
            AuthenticationAuditListener.AUTHENTICATION_FAILURE, data));
}

 
2、AuthorizationFailure Event 이벤트인 경우 Audit Event 이벤트를 보내고, type은 AUTHORIZATIONFAILURE.코드는 다음과 같습니다.
private void onAuthorizationFailureEvent(AuthorizationFailureEvent event) {
    Map data = new HashMap();
    data.put("type", event.getAccessDeniedException().getClass().getName());
    data.put("message", event.getAccessDeniedException().getMessage());
    if (event.getAuthentication().getDetails() != null) {
        data.put("details", event.getAuthentication().getDetails());
    }
    publish(new AuditEvent(event.getAuthentication().getName(), AUTHORIZATION_FAILURE,
            data));
}

 
자동 어셈블:
AuditAutoConfiguration에서 다음과 같은 코드로 어셈블되었습니다.
@Bean
@ConditionalOnClass(name = "org.springframework.security.access.event.AbstractAuthorizationEvent")
@ConditionalOnMissingBean(AbstractAuthorizationAuditListener.class)
public AuthorizationAuditListener authorizationAuditListener() throws Exception {
    return new AuthorizationAuditListener();
}
  • @Bean –> ID 1개는 authorizationAuditListener, 유형은 AuthorizationAuditListener의 bean
  • 등록
  • @Conditional Onclass(name = "org.springframework.security.access.event.Abstract Authorization Event") -> 현재 클래스 경로에 org가 있습니다.springframework.security.access.event.AbstractAuthorization Event 시 적용
  • @Conditional OnMissingBean(Abstract Authorization Audit Listener.class) –>beanFactory에 Abstract Authorization Audit Listener 유형의 bean이 존재하지 않을 때 효력이 발생합니다.

  • 3. 절차 분석


    스프링 boot 애플리케이션에서 Audit Event의 이벤트 처리를 활성화하려면 다음과 같이 스프링-boot-starter-security 의존도를 추가해야 합니다.
    
        org.springframework.boot
        spring-boot-starter-security
    

    의존만으로는 부족합니다. 우리는 보안 설정에 가입해야 합니다. 그렇지 않으면 Authorization Audit Listener, Authentication Audit Listener가 어떤 사건을 감청해야 합니까?따라서 다음과 같은 코드가 포함되어 있습니다.
    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().antMatchers("/error-log").hasAuthority("ROLE_TEST").antMatchers("/", "/home")
                    .permitAll().anyRequest().authenticated().and().formLogin().loginPage("/login").permitAll().and()
                    .logout().logoutUrl("/logout").permitAll().and().authorizeRequests();
    
        }
    
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
        }
    }

     
    configure Global에서 메모리에 사용자 이름은 user이고 비밀번호는password이며 역할은 USER입니다.configure에서는 다음과 같이 구성했습니다.
  • /error-log에 액세스하려면 ROLE 필요TEST 권한
  • 액세스/,/home은 검증 필요 없음
  • 로그인 페이지는/login이며 인증 필요 없음
  • 로그아웃 페이지는/logout
  • 기타 링크는 모두 검증이 필요합니다
  • 다음 코드의 User Controller 1개를 선언합니다.
    @Controller
    public class UserController {
    
        @RequestMapping("/")
        public String index() {
            return "index";
        }
    
        @RequestMapping("/hello")
        public String hello() {
            return "hello";
        }
    
        @RequestMapping(value = "/login", method = RequestMethod.GET)
        public String login() {
            return "login";
        }
    
        @RequestMapping("/error-test")
        public String error() {
            return "1";
        }   
    } 

     
    src/main/resources/templates 디렉토리에 다음과 같은 페이지를 만듭니다.
    hello.html, 코드는 다음과 같습니다.
    
    
          xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    
        Hello World!
    
    
    

    Hello [[${#httpServletRequest.remoteUser}]]!

     
    index.html, 코드는 다음과 같습니다.
    
    
          xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    
        Spring Security  
    
    
    

    Spring Security에 오신 것을 환영합니다!

    여기.


     
    login.html, 코드는 다음과 같습니다.
    
    
          xmlns:th="http://www.thymeleaf.org"
          xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
        
            Spring Security Example 
        
        
            
    if="${param.error}">
    if="${param.logout}">
    사용자 이름:
    암호:
     
    테스트
    응용 프로그램을 시작한 후 다음과 같은 링크에 액세스합니다.http://127.0.0.1:8080/다음 페이지로 돌아갑니다.
     
    index를 클릭하십시오.html의 하이퍼링크 후 검증이 필요하기 때문에login 페이지로 돌아갑니다. 그림:
     
    잘못된 사용자 이름, 암호를 입력하고 다음 페이지로 돌아갑니다.
     
    사용자, password 를 입력한 후 다음 페이지로 돌아갑니다.
     
    로그아웃을 클릭하면 페이지가 다음과 같습니다.
     
    지금 방문http://127.0.0.1:8080/error-test, 로그인하지 않았기 때문에 로그인 페이지로 돌아갑니다.
    방문http://127.0.0.1:8080/auditevents를 반환한 결과는 다음과 같습니다.
    {
    events: [
        {
        timestamp: "2018-01-23T03:52:13+0000",
        principal: "anonymousUser",
        type: "AUTHORIZATION_FAILURE",
        data: {
        details: {
        remoteAddress: "127.0.0.1",
        sessionId: null
        },
        type: "org.springframework.security.access.AccessDeniedException",
        message: "Access is denied"
        }
    },
        {
        timestamp: "2018-01-23T03:54:21+0000",
        principal: "aaa",
        type: "AUTHENTICATION_FAILURE",
        data: {
        details: {
        remoteAddress: "127.0.0.1",
        sessionId: "DFDB023AEEF41BBD8079EC32402CBFD8"
        },
        type: "org.springframework.security.authentication.BadCredentialsException",
        message: "Bad credentials"
        }
        },
        {
        timestamp: "2018-01-23T03:55:50+0000",
        principal: "user",
        type: "AUTHENTICATION_SUCCESS",
        data: {
        details: {
        remoteAddress: "127.0.0.1",
        sessionId: "DFDB023AEEF41BBD8079EC32402CBFD8"
        }
        }
        },
        {
        timestamp: "2018-01-23T03:58:38+0000",
        principal: "anonymousUser",
        type: "AUTHORIZATION_FAILURE",
        data: {
        details: {
        remoteAddress: "127.0.0.1",
        sessionId: "6E6E614D638B6F5EE5B7E8CF516E2534"
        },
        type: "org.springframework.security.access.AccessDeniedException",
        message: "Access is denied"
        }
        },
        {
        timestamp: "2018-01-23T04:00:01+0000",
        principal: "anonymousUser",
        type: "AUTHORIZATION_FAILURE",
        data: {
        details: {
        remoteAddress: "127.0.0.1",
        sessionId: "6E6E614D638B6F5EE5B7E8CF516E2534"
        },
        type: "org.springframework.security.access.AccessDeniedException",
        message: "Access is denied"
        }
        },
        {
        timestamp: "2018-01-23T04:00:12+0000",
        principal: "user",
        type: "AUTHENTICATION_SUCCESS",
        data: {
        details: {
        remoteAddress: "127.0.0.1",
        sessionId: "6E6E614D638B6F5EE5B7E8CF516E2534"
        }
        }
        }
    ]
    }

     
    해석
  • 방문할 때http://127.0.0.1:8080/hello.html시, 검증이 필요하기 때문에 Authorization Failure Event 이벤트를 보내고, 이때는 Authorization Audit Listener에 의해 처리되며, onAuthorization Failure Event 방법을 호출합니다.AuditEvent 이벤트 보내기
  • Audit Listener는 이 사건을 감청하고 최종적으로 onAudit Event 방법을 실행하여Audit Event를 InMemory Audit Event Repository에 저장합니다.
  • 이때login에 있습니다.html에서 잘못된 사용자 이름, 비밀번호를 입력하면 Authentication Failure BadCredential Event 이벤트를 보내고 Authentication Audit Listener에 맡기고 최종적으로 onAuthentication Failure Event 방법을 실행하고 Audit Event 이벤트를 보냅니다. 최종적으로 Audit Listener에 이벤트를 저장합니다
  • .
  • 이때 저희가 정확한 사용자 이름 비밀번호를 입력하면 Authentication Success Event 이벤트를 보내서 Authentication Audit Listener 이벤트 처리에 맡기고 최종적으로 onAuthentication Success Event 방법을 실행하여 Audit Event 이벤트를 보내며 최종적으로 Audit Listener에서 이벤트를 InMemory Audit Event Repository에 저장합니다
  • 이후에SessionFixationProtection Event 이벤트가 발생하여AuthenticationAuditListener가 처리하지 않음
  • Interactive Authentication Success Event가 발생하고,Authentication Audit Listener가 처리하지 않습니다.
  • 이때 Hello로 이동합니다.html, 우리가 로그아웃을 클릭한 후 어떠한 이벤트도 발생하지 않았습니다.
  • 로그온에 성공하면 ROLE 이 필요하므로/error-log에 액세스합니다.TEST 권한, user는 ROLEAuthorization Failure Event 이벤트가 발생하기 때문에 Authorization Audit Listener에 맡기고 Audit Event 이벤트를 보내며 최종적으로 Audit Listener에서 이벤트를 InMemory Audit Event Repository에 저장합니다
  • zhuan:https://blog.csdn.net/qq_26000415/article/details/79138270

    좋은 웹페이지 즐겨찾기