浏览代码

增加AuthorizationListener

zhouhao 8 年之前
父节点
当前提交
89b2c43359
共有 16 个文件被更改,包括 485 次插入85 次删除
  1. 29 0
      hsweb-authorization/hsweb-authorization-api/README.md
  2. 0 1
      hsweb-authorization/hsweb-authorization-api/pom.xml
  3. 16 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/AuthorizationListener.java
  4. 49 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/AuthorizationListenerDispatcher.java
  5. 0 27
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/UserAuthorizationConfigRegister.java
  6. 0 43
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/UserAuthorizationListener.java
  7. 64 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AbstractAuthorizationEvent.java
  8. 34 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationBeforeEvent.java
  9. 43 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationDecodeEvent.java
  10. 33 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationEvent.java
  11. 38 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationExitEvent.java
  12. 63 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationFailedEvent.java
  13. 52 0
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationSuccessEvent.java
  14. 18 14
      hsweb-authorization/hsweb-authorization-shiro/src/main/java/org/hswebframework/web/authorization/shiro/ListenerAuthorizingRealm.java
  15. 40 0
      hsweb-authorization/hsweb-authorization-shiro/src/main/java/org/hswebframework/web/authorization/shiro/LoginExitListener.java
  16. 6 0
      hsweb-authorization/hsweb-authorization-shiro/src/main/java/org/hswebframework/web/authorization/shiro/ShiroAutoconfiguration.java

+ 29 - 0
hsweb-authorization/hsweb-authorization-api/README.md

@@ -23,3 +23,32 @@ _点击名称,查看源代码注释获得使用说明_
 | ------------- |:-------------:| 
 | [`Authorization`](src/main/java/org/hswebframework/web/authorization/Authorization.java)    | 用户的认证信息 | 
 | [`AuthorizationHolder`](src/main/java/org/hswebframework/web/authorization/AuthorizationHolder.java)      | 用于获取当前登录用户的认证信息      | 
+
+
+### Listener
+api提供[AuthorizationListener](src/main/java/org/hswebframework/web/authorization/listener/AuthorizationListener.java)
+来进行授权逻辑拓展,在授权前后执行可自定义的操作.如rsa解密帐号密码,验证码判断等。
+
+默认事件列表():
+
+| 类名       | 说明          | 
+| ------------- |:-------------:| 
+| [`AuthorizationDecodeEvent`](src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationDecodeEvent.java)    | 接收到请求参数时 | 
+| [`AuthorizationBeforeEvent`](src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationBeforeEvent.java)      | 验证密码前触发      | 
+| [`AuthorizationFailedEvent`](src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationFailedEvent.java)      | 授权验证失败时触发      | 
+| [`AuthorizationSuccessEvent`](src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationSuccessEvent.java)      | 授权成功时触发      | 
+| [`AuthorizationExitEvent`](src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationExitEvent.java)      | 用户注销时触发      | 
+
+例子:
+
+```java
+@Component
+public class CustomAuthorizationSuccessListener implements AuthorizationListener<AuthorizationSuccessEvent>{
+        @Override
+        public void on(AuthorizationSuccessEvent event) {
+            Authorization authorization=event.getAuthorization();
+            //....
+            System.out.println(authorization.getUser().getName()+"登录啦");
+        }
+}
+```

+ 0 - 1
hsweb-authorization/hsweb-authorization-api/pom.xml

@@ -11,5 +11,4 @@
 
     <artifactId>hsweb-authorization-api</artifactId>
 
-
 </project>

+ 16 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/AuthorizationListener.java

@@ -0,0 +1,16 @@
+
+package org.hswebframework.web.authorization.listener;
+
+
+import org.hswebframework.web.authorization.listener.event.AuthorizationEvent;
+
+/**
+ * 授权监听器,用于监听授权过程,以及自定义授权逻辑
+ *
+ * @author zhouhao
+ * @see AuthorizationEvent
+ * @since 3.0
+ */
+public interface AuthorizationListener<E extends AuthorizationEvent> {
+    void on(E event);
+}

+ 49 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/AuthorizationListenerDispatcher.java

@@ -0,0 +1,49 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.authorization.listener;
+
+import org.hswebframework.web.authorization.listener.event.AuthorizationEvent;
+
+import java.util.*;
+
+/**
+ * @author zhouhao
+ */
+public class AuthorizationListenerDispatcher {
+
+    private Map<Class<? extends AuthorizationEvent>, List<AuthorizationListener>> listenerStore = new HashMap<>();
+
+    public <E extends AuthorizationEvent> void addListener(Class<E> eventClass, AuthorizationListener<E> listener) {
+        listenerStore.computeIfAbsent(eventClass, (k) -> new LinkedList<>())
+                .add(listener);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <E extends AuthorizationEvent> void doEvent(Class<E> eventType, E event) {
+        List<AuthorizationListener<E>> store = (List) listenerStore.get(eventType);
+        if (null != store) {
+            store.forEach(listener -> listener.on(event));
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public <E extends AuthorizationEvent> void doEvent(E event) {
+        doEvent((Class<E>) event.getClass(), event);
+    }
+}

+ 0 - 27
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/UserAuthorizationConfigRegister.java

@@ -1,27 +0,0 @@
-/*
- * Copyright 2016 http://www.hswebframework.org
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- */
-
-package org.hswebframework.web.authorization.listener;
-
-/**
- * TODO 完成注释
- *
- * @author zhouhao
- */
-public interface UserAuthorizationConfigRegister {
-    void setUseVerifyCode(boolean useVerifyCode);
-}

+ 0 - 43
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/UserAuthorizationListener.java

@@ -1,43 +0,0 @@
-/*
- * Copyright 2016 http://www.hswebframework.org
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- */
-
-package org.hswebframework.web.authorization.listener;
-
-
-import org.hswebframework.web.authorization.Authorization;
-
-/**
- * TODO 完成注释
- *
- * @author zhouhao
- */
-public interface UserAuthorizationListener {
-
-    default void onConfig(String username, UserAuthorizationConfigRegister configHolder) {
-    }
-
-    default void onAuthorizeBefore(String username) {
-    }
-
-    default void onAuthorizeFail(String username) {
-    }
-
-    default void onLoginOut(Authorization authorization){
-
-    }
-    void onAuthorizeSuccess(boolean isRemembered, Authorization authorization);
-}

+ 64 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AbstractAuthorizationEvent.java

@@ -0,0 +1,64 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.authorization.listener.event;
+
+
+import java.util.Optional;
+import java.util.function.Function;
+
+/**
+ * 抽象授权事件,保存事件常用的数据
+ *
+ * @author zhouhao
+ * @since 3.0
+ */
+public abstract class AbstractAuthorizationEvent implements AuthorizationEvent {
+    protected String username;
+
+    protected String password;
+
+    private Function<String, Object> parameterGetter;
+
+    /**
+     * 带参构造方法,所有参数不能为null
+     *
+     * @param username        用户名
+     * @param password        密码
+     * @param parameterGetter 参数获取函数,用户获取授权时传入的参数
+     */
+    public AbstractAuthorizationEvent(String username, String password, Function<String, Object> parameterGetter) {
+        if (username == null || password == null || parameterGetter == null) throw new NullPointerException();
+        this.username = username;
+        this.password = password;
+        this.parameterGetter = parameterGetter;
+    }
+
+    @SuppressWarnings("unchecked")
+    protected <T> Optional<T> getParameter(String name) {
+        return Optional.ofNullable((T) parameterGetter.apply(name));
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+}

+ 34 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationBeforeEvent.java

@@ -0,0 +1,34 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.authorization.listener.event;
+
+import java.util.function.Function;
+
+/**
+ * 授权前事件
+ *
+ * @author zhouhao
+ * @since 3.0
+ */
+public class AuthorizationBeforeEvent extends AbstractAuthorizationEvent {
+
+    public AuthorizationBeforeEvent(String username, String password, Function<String, Object> parameterGetter) {
+        super(username, password, parameterGetter);
+    }
+}

+ 43 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationDecodeEvent.java

@@ -0,0 +1,43 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.authorization.listener.event;
+
+import java.util.function.Function;
+
+/**
+ * 在进行授权时的最开始,触发此事件进行用户名密码解码,解码后请调用{@link #setUsername(String)} {@link #setPassword(String)}重新设置用户名密码
+ *
+ * @author zhouhao
+ * @since 3.0
+ */
+public class AuthorizationDecodeEvent extends AbstractAuthorizationEvent {
+
+    public AuthorizationDecodeEvent(String username, String password, Function<String, Object> parameterGetter) {
+        super(username, password, parameterGetter);
+    }
+
+    public void setUsername(String username) {
+        super.username = username;
+    }
+
+    public void setPassword(String password) {
+        super.username = password;
+    }
+
+}

+ 33 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationEvent.java

@@ -0,0 +1,33 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.authorization.listener.event;
+
+/**
+ * 授权事件
+ *
+ * @author zhouhao
+ * @see AuthorizationSuccessEvent
+ * @see AuthorizationFailedEvent
+ * @see AuthorizationBeforeEvent
+ * @see AuthorizationDecodeEvent
+ * @see AuthorizationExitEvent
+ * @since 3.0
+ */
+public interface AuthorizationEvent {
+}

+ 38 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationExitEvent.java

@@ -0,0 +1,38 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.authorization.listener.event;
+
+import org.hswebframework.web.authorization.Authorization;
+
+/**
+ * 退出登录事件
+ *
+ * @author zhouhao
+ */
+public class AuthorizationExitEvent implements AuthorizationEvent {
+    private Authorization authorization;
+
+    public AuthorizationExitEvent(Authorization authorization) {
+        this.authorization = authorization;
+    }
+
+    public Authorization getAuthorization() {
+        return authorization;
+    }
+}

+ 63 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationFailedEvent.java

@@ -0,0 +1,63 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.authorization.listener.event;
+
+import java.util.function.Function;
+
+/**
+ * 授权失败时触发
+ *
+ * @author zhouhao
+ */
+public class AuthorizationFailedEvent extends AbstractAuthorizationEvent {
+
+    /**
+     * 失败原因
+     */
+    private Reason reason;
+
+    /**
+     * 异常信息
+     */
+    private Exception exception;
+
+    public AuthorizationFailedEvent(String username,
+                                    String password,
+                                    Function<String, Object> parameterGetter,
+                                    Reason reason) {
+        super(username, password, parameterGetter);
+        this.reason = reason;
+    }
+
+    public Exception getException() {
+        return exception;
+    }
+
+    public void setException(Exception exception) {
+        this.exception = exception;
+    }
+
+    public Reason getReason() {
+        return reason;
+    }
+
+    public enum Reason {
+        PASSWORD_ERROR, USER_DISABLED, USER_NOT_EXISTS, OTHER
+    }
+}

+ 52 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/listener/event/AuthorizationSuccessEvent.java

@@ -0,0 +1,52 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.authorization.listener.event;
+
+import org.hswebframework.web.authorization.Authorization;
+
+import java.util.Optional;
+import java.util.function.Function;
+
+/**
+ * 授权成功事件,当授权成功时,触发此事件,并传入授权的信息
+ *
+ * @author zhouhao
+ * @see Authorization
+ * @since 3.0
+ */
+public class AuthorizationSuccessEvent implements AuthorizationEvent {
+    private Authorization authorization;
+
+    private Function<String,Object> parameterGetter;
+
+    public AuthorizationSuccessEvent(Authorization authorization, Function<String, Object> parameterGetter) {
+        this.authorization = authorization;
+        this.parameterGetter = parameterGetter;
+    }
+
+    public Authorization getAuthorization() {
+        return authorization;
+    }
+
+    @SuppressWarnings("unchecked")
+    public  <T> Optional<T> getParameter(String name) {
+        return Optional.ofNullable((T) parameterGetter.apply(name));
+    }
+
+}

+ 18 - 14
hsweb-authorization/hsweb-authorization-shiro/src/main/java/org/hswebframework/web/authorization/shiro/ListenerAuthorizingRealm.java

@@ -31,14 +31,16 @@ import org.apache.shiro.subject.PrincipalCollection;
 import org.apache.shiro.subject.Subject;
 import org.hswebframework.web.authorization.Authorization;
 import org.hswebframework.web.authorization.Role;
-import org.hswebframework.web.authorization.listener.UserAuthorizationListener;
+import org.hswebframework.web.authorization.listener.AuthorizationListener;
+import org.hswebframework.web.authorization.listener.event.AuthorizationSuccessEvent;
 
 import java.util.stream.Collectors;
 
 /**
  * @author zhouhao
  */
-public class ListenerAuthorizingRealm extends AuthorizingRealm implements UserAuthorizationListener {
+public class ListenerAuthorizingRealm extends AuthorizingRealm
+        implements AuthorizationListener<AuthorizationSuccessEvent> {
 
     public ListenerAuthorizingRealm() {
         setAuthenticationTokenClass(SimpleAuthenticationToken.class);
@@ -66,15 +68,25 @@ public class ListenerAuthorizingRealm extends AuthorizingRealm implements UserAu
                 authorization.getUser().getId(), ListenerAuthorizingRealm.class.getName());
     }
 
-    @Override
-    public void onLoginOut(Authorization authorization) {
+    public void loginOut(Authorization authorization) {
         if (null != authorization)
             getCache(authorization.getUser().getUsername()).clear();
         SecurityUtils.getSubject().logout();
     }
 
+    protected <K, V> Cache<K, V> getCache(String name) {
+        return getCacheManager().getCache(getCacheName(name));
+    }
+
+    protected String getCacheName(String name) {
+        return "shiro.auth.info.".concat(name);
+    }
+
     @Override
-    public void onAuthorizeSuccess(boolean isRemembered, Authorization authorization) {
+    public void on(AuthorizationSuccessEvent event) {
+        Authorization authorization = event.getAuthorization();
+        boolean remember = Boolean.TRUE.equals(event.getParameter("remember").orElse(false));
+
         SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
         authorizationInfo.addRoles(authorization.getRoles().stream().map(Role::getId).collect(Collectors.toList()));
         authorizationInfo.addObjectPermissions(
@@ -95,15 +107,7 @@ public class ListenerAuthorizingRealm extends AuthorizingRealm implements UserAu
                 .put(AuthenticationInfo.class.getName(), createAuthenticationInfo(authorization));
 
         Subject subject = SecurityUtils.getSubject();
-        subject.login(new SimpleAuthenticationToken(authorization, isRemembered));
+        subject.login(new SimpleAuthenticationToken(authorization, remember));
         subject.getSession().setAttribute(Authorization.class.getName(), authorization);
     }
-
-    protected <K, V> Cache<K, V> getCache(String name) {
-        return getCacheManager().getCache(getCacheName(name));
-    }
-
-    protected String getCacheName(String name) {
-        return "shiro.auth.info.".concat(name);
-    }
 }

+ 40 - 0
hsweb-authorization/hsweb-authorization-shiro/src/main/java/org/hswebframework/web/authorization/shiro/LoginExitListener.java

@@ -0,0 +1,40 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.authorization.shiro;
+
+import org.hswebframework.web.authorization.listener.AuthorizationListener;
+import org.hswebframework.web.authorization.listener.event.AuthorizationExitEvent;
+
+/**
+ *
+ * @author zhouhao
+ */
+public class LoginExitListener implements AuthorizationListener<AuthorizationExitEvent> {
+
+    private ListenerAuthorizingRealm listenerAuthorizingRealm;
+
+    public LoginExitListener(ListenerAuthorizingRealm listenerAuthorizingRealm) {
+        this.listenerAuthorizingRealm = listenerAuthorizingRealm;
+    }
+
+    @Override
+    public void on(AuthorizationExitEvent event) {
+        listenerAuthorizingRealm.loginOut(event.getAuthorization());
+    }
+}

+ 6 - 0
hsweb-authorization/hsweb-authorization-shiro/src/main/java/org/hswebframework/web/authorization/shiro/ShiroAutoconfiguration.java

@@ -94,12 +94,18 @@ public class ShiroAutoconfiguration {
     }
 
     @Bean
+    @Order(Ordered.LOWEST_PRECEDENCE)
     public ListenerAuthorizingRealm listenerAuthorizingRealm(CacheManager cacheManager) {
         ListenerAuthorizingRealm realm = new ListenerAuthorizingRealm();
         realm.setCacheManager(cacheManager);
         return realm;
     }
 
+    @Bean
+    public LoginExitListener loginExitListener(ListenerAuthorizingRealm listenerAuthorizingRealm) {
+        return new LoginExitListener(listenerAuthorizingRealm);
+    }
+
     @Bean(name = "lifecycleBeanPostProcessor")
     public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
         return new LifecycleBeanPostProcessor();