91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

spring boot + shiro 動態更新用戶信息

發布時間:2020-09-21 03:49:48 來源:網絡 閱讀:64066 作者:wyait 欄目:開發技術

spring boot + shiro 動態更新用戶信息

場景

用戶A在線,管理員在后臺更改了用戶A信息(資料或權限)之后;用戶A再進行下一步操作時,會被攔截并退出登錄狀態,再登錄才可以執行操作;來確保用戶A的信息同步更新。

后臺權限管理系統

技術實現

前篇:

  • spring boot + mybatis + layui + shiro后臺權限管理系統:https://blog.51cto.com/wyait/2082803
  • springboot + shiro之登錄人數限制、登錄判斷重定向、session時間設置:https://blog.51cto.com/wyait/2107423

基于前篇,新增功能:

  1. 新增用戶表版本version字段;
  2. 更新用戶操作時,通過version字段來保證數據一致;
  3. 新增通過攔截器實現動態更新用戶信息(用戶資料、用戶權限);
  4. 新增登錄成功后默認頁面home.html;
  5. 頁面操作細節優化

wyait-manage、wyait-manage-1.2.0源碼都更新了以上功能!

以及新增了springboot項目,開發和線上jdk版本不一致導致項目無法啟動、無法加載的問題的排查及解決思路。

后篇:

  • springboot + shiro 權限注解、統一異常處理、請求亂碼解決 :https://blog.51cto.com/wyait/2125708

項目源碼:(包含數據庫源碼)

github源碼: https://github.com/wyait/manage.git
碼云:https://gitee.com/wyait/manage.git
github對應項目源碼目錄:wyait-manage-1.2.0
碼云對應項目源碼目錄:wyait-manage-1.2.0

動態更新用戶權限實現

使用shiro可能會遇到修改了用戶權限后,沒有立即生效,需要等到用戶重新登錄后才能生效;不能立即同步更新,顯然是不合理的。

解決方案

【實測無效】!!!
授權方法,是在shiro進行鑒權的時候才能觸發。只是配置了authc/user/anon等,不會觸發;
perms,port,rest,roles,ssl等,會觸發授權方法doGetAuthorizationInfo。

  1. 自定義ShiroRealm中添加清除全部用戶權限緩存的方法:
/**
 * 清除所有緩存
 */
public void clearCachedAuth(){
    this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
}
  1. 在更新用戶權限的地方調用該方法,清除緩存:
//清除ehcache中所有用戶權限緩存
RealmSecurityManager rsm = (RealmSecurityManager)SecurityUtils.getSecurityManager();
ShiroRealm authRealm = (ShiroRealm)rsm.getRealms().iterator().next();
authRealm.clearCachedAuth();
  1. 想要達到的效果:在用戶進行后臺請求的時候,無緩存就會再次請求授權方法,更新自己的權限。
    實測,無效!緩存依然存在!原因可能是使用ehcache導致的。

實際解決方案參考下文中的方案二!

動態更新用戶信息(用戶資料、用戶權限)

在系統中,由管理員更改了用戶A信息后,如果用戶A在線,無法及時更新相關的改動;
更新用戶資料、權限等信息,如果該用戶在線,同步更新用戶信息解決方案:

方案一【不推薦】:SessionDAO控制

在ShiroRealm中通過SessionDAO拿到所有在線的用戶,

Collection<Session> sessions = sessionDAO.getActiveSessions();

遍歷找到匹配的,根據情況,退出登錄或更新用戶信息:

@Autowired

private SessionDAO sessionDAO;

public void updateShiroUser(String loginName){

    Collection<Session> sessions = sessionDAO.getActiveSessions();
    for(Session session:sessions){
        if(loginName.equals(String.valueOf(session.getAttribute(DefaultSubjeContext.PRINCIPALS_SESSION_KEY))) {
            //設置session立即失效,即將其踢出系統
            session.setTimeout(0);
            //TODO 或更新下用戶信息
            break;
        }   

    }

不推薦理由

  • 用戶數量太大的時候,效率問題。

方案二【推薦】:用戶表新增版本控制

用戶信息新增version版本標記,寫個攔截器,每次請求判斷version是否一致,如有改動,根據情況,退出或更新用戶信息(本文統一做了退出登錄處理,可以結合實際需求做相應調整)。

這個方案,基于樂觀鎖原理實現。同樣可解決動態更新用戶權限的問題。

user用戶表新增字段version
ALTER TABLE `user`
MODIFY COLUMN `id`  int(10) NOT NULL AUTO_INCREMENT FIRST ,
ADD COLUMN `version`  int(10) NULL DEFAULT 0 COMMENT '更新版本' AFTER `send_time`;

TODO【詳見源碼】

  • 更新對應的pojo實體類和mapper文件
  • 完善用戶更新操作,版本控制;
新建攔截器類
  1. 自定義攔截器UserActionInterceptor實現接口HandlerInterceptor:
/**
 * 
 * @項目名稱:wyait-manage
 * @類名稱:UserActionInterceptor
 * @類描述:判斷用戶信息是否已被后臺更改,并根據更改的情況做對應的處理
 * @創建人:wyait
 * @創建時間:2018年5月2日 上午9:36:43 
 * @version:
 */
public class UserActionInterceptor implements HandlerInterceptor {

    private static Logger logger = LoggerFactory
            .getLogger(UserActionInterceptor.class);

    @Autowired
    private UserService userService;

    ... ...

    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object obj, Exception e)
            throws Exception {
        // TODO Auto-generated method stub
    }

    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object obj, ModelAndView mv)
            throws Exception {
        // TODO Auto-generated method stub
    }

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object obj) throws Exception {
        // TODO Auto-generated method stub
        logger.debug("請求到達后臺方法之前調用(controller之前)");
        // 1. SecurityUtils獲取session中的用戶信息
        // HttpSession session=request.getSession();
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        if (user != null && StringUtils.isNotEmpty(user.getMobile())
                && null != user.getVersion()) {
            // 2. 獲取數據庫中的用戶數據
            User dataUser = this.userService.findUserByMobile(user.getMobile());
            // 3. 對比session中用戶的version和數據庫中的是否一致
            if (dataUser != null
                    && null != dataUser.getVersion()
                    && String.valueOf(user.getVersion()).equals(
                            String.valueOf(dataUser.getVersion()))) {
                // 3.1 一樣,放行
                return true;
            }else{
                // 3.2 不一樣,這里統一做退出登錄處理;//TODO 使用redis緩存用戶權限數據,根據用戶更新、用戶權限更新;做對應的處理。
                SecurityUtils.getSubject().logout();
                isAjaxResponse(request,response);
            }
        }
        return false;
    }

    ... ...
}
  1. 自定義MyWebMvcConfig繼承WebMvcConfigurerAdapter
/**
 * 
 * @項目名稱:wyait-manage
 * @類名稱:MyWebMvcConfig
 * @類描述:自定義靜態資源映射路徑和靜態資源存放路徑
 * @創建人:wyait
 * @修改時間:2018年5月3日09:55:23
 * @version:
 */
@Configuration
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {

    /**
     * 添加攔截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 路徑根據后期項目的擴展,進行調整
        registry.addInterceptor(new UserActionInterceptor())
                .addPathPatterns("/user/**", "/auth/**")
                .excludePathPatterns("/user/sendMsg", "/user/login");
        super.addInterceptors(registry);
    }

}
  1. IStatusMessage接口和common.js中新增判斷‘1102’狀態碼;【詳見源碼】
  2. 啟動,測試
報錯

錯誤信息:

java.lang.NullPointerException: null
    at com.wyait.manage.interceptor.UserActionInterceptor.preHandle(UserActionInterceptor.java:62) ~[classes/:?]
    at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:133) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:962) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]

userService對象為null,無法注入UserService。

    @Autowired
    private UserService userService;
  • 解決方案:
    在Spring添加攔截器之前先創建這個Spring Bean攔截器,這樣就能在Spring映射這個攔截器前,把攔截器中的依賴注入的對象給初始化完成了。避免攔截器中注入的對象為null問題。
@Configuration
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {
    /**
     * 
     * @描述:在Spring添加攔截器之前先創建攔截器對象,這樣就能在Spring映射這個攔截器前,把攔截器中的依賴注入的對象給初始化完成了。
     * </br>避免攔截器中注入的對象為null問題。
     * @創建人:wyait
     * @創建時間:2018年5月3日 上午10:07:36
     * @return
     */
    @Bean
    public UserActionInterceptor userActionInterceptor(){
        return new UserActionInterceptor();
    }

    /**
     * 添加攔截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 路徑根據后期項目的擴展,進行調整
        registry.addInterceptor(userActionInterceptor())
                .addPathPatterns("/user/**", "/auth/**")
                .excludePathPatterns("/user/sendMsg", "/user/login");
        super.addInterceptors(registry);
    }

}

注意

分布式或集群的時候,需要解決session共享問題;相關的方案有:session持久化、redis或其他中間件、nginx的ip_hash、cookie實現、服務器間Session同步等;這時候處理動態更新用戶信息,需要結合實際情況而定;

后期會更新redis版本。

jdk版本引發的錯誤

部署環境

linux 6.* 系統

jdk 1.7
tomcat 7.*
maven 3.3.3

線上tomcat啟動logs

五月 08, 2018 11:49:23 上午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://shiro.apache.org/tags is already defined
五月 08, 2018 11:49:23 上午 org.apache.catalina.startup.TldConfig execute
信息: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
五月 08, 2018 11:51:03 上午 org.apache.catalina.util.SessionIdGeneratorBase createSecureRandom
信息: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [112,917] milliseconds.
五月 08, 2018 11:51:03 上午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deployment of web application directory /usr/tools/tomcat-9190/webapps/ROOT has finished in 117,517 ms
五月 08, 2018 11:51:03 上午 org.apache.catalina.startup.Catalina start
信息: Server startup in 117563 ms
五月 08, 2018 11:51:37 上午 org.apache.catalina.util.SessionIdGeneratorBase createSecureRandom
信息: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [134,439] milliseconds.
...

無明顯錯誤,但是項目沒有加載成功,訪問是404.

  • 可能的問題點:
At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

對比本地tomcat7和線上tomcat7啟動,會出現tomcat7和8版本沖突問題,本地解決了,線上依舊啟動不成功;再百度、google方案,大致是tomcat版本問題而打印的日志信息,按照搜索的方案配置,均未解決。

考慮應該是環境配置的版本不一致導致的項目無法加載啟動成功,確認并排查下開發、測試、線上的jdk、tomcat等版本是否一致。

原因及解決方案

  1. jdk版本
    確認linux和window的jdk版本是否一致
    • windows查看jdk版本,dos窗口
java -version

jdk 1.8

  • linux系統查看jdk版本
java -v

jdk 1.7
這就是導致項目在linux系統啟動不起來的原因:開發和線上的jdk版本不一致!!!

將windows的jdk版本切換為jdk1.7,重新打開新的dos窗口:java -version;jdk顯示為1.7.*。版本切換成功!

  1. maven重新打包,報錯:
...
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.
1:compile (default-compile) on project wyait-manage: Fatal error compiling: 無效的
目標發行版: 1.8 -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e swit
ch.
...
  • 查看setting配置文件,找到<profile>配置:
<!--
<profile>    
        <id>jdk-1.8</id>    
        <activation>    
            <activeByDefault>true</activeByDefault>    
            <jdk>1.8</jdk>    
        </activation>    
        <properties>    
            <maven.compiler.source>1.8</maven.compiler.source>    
            <maven.compiler.target>1.8</maven.compiler.target>    
            <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>    
        </properties>     
    </profile> 
    -->

注釋掉這一段maven指定jdk為1.8版本的配置;重新打包,成功!

  1. 重新部署到linux系統,啟動并訪問成功!
    問題解決。

總結

開發過程中,要確保開發、測試、線上配置的環境(jdk、maven、tomcat等開發依賴的環境支持)保持一致。避免出現由于開發環境中的版本不一致而出現問題,導致項目上線出問題和延遲項目上線時間!


前篇:

  • spring boot + mybatis + layui + shiro后臺權限管理系統:https://blog.51cto.com/wyait/2082803
  • springboot + shiro之登錄人數限制、登錄判斷重定向、session時間設置:https://blog.51cto.com/wyait/2107423

后篇:

  • springboot + shiro 權限注解、統一異常處理、請求亂碼解決 :https://blog.51cto.com/wyait/2125708

項目源碼:(包含數據庫源碼)
github源碼: https://github.com/wyait/manage.git
碼云:https://gitee.com/wyait/manage.git
github對應項目源碼目錄:wyait-manage-1.2.0
碼云對應項目源碼目錄:wyait-manage-1.2.0

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

上蔡县| 锦州市| 峡江县| 长宁区| 施秉县| 文昌市| 宁阳县| 闻喜县| 会同县| 彭州市| 博白县| 白沙| 宜丰县| 墨玉县| 桑日县| 丹东市| 济源市| 奉节县| 富源县| 乐都县| 体育| 磴口县| 上栗县| 宜昌市| 焦作市| 洛宁县| 佳木斯市| 青岛市| 尚志市| 和田市| 五莲县| 五大连池市| 河间市| 西贡区| 沅陵县| 西丰县| 雷波县| 云和县| 清水县| 威海市| 蒲江县|