您好,登錄后才能下訂單哦!
用戶A在線,管理員在后臺更改了用戶A信息(資料或權(quán)限)之后;用戶A再進(jìn)行下一步操作時,會被攔截并退出登錄狀態(tài),再登錄才可以執(zhí)行操作;來確保用戶A的信息同步更新。
前篇:
基于前篇,新增功能:
wyait-manage、wyait-manage-1.2.0源碼都更新了以上功能!
以及新增了springboot項目,開發(fā)和線上jdk版本不一致導(dǎo)致項目無法啟動、無法加載的問題的排查及解決思路。
后篇:
github源碼: https://github.com/wyait/manage.git
碼云:https://gitee.com/wyait/manage.git
github對應(yīng)項目源碼目錄:wyait-manage-1.2.0
碼云對應(yīng)項目源碼目錄:wyait-manage-1.2.0
使用shiro可能會遇到修改了用戶權(quán)限后,沒有立即生效,需要等到用戶重新登錄后才能生效;不能立即同步更新,顯然是不合理的。
【實測無效】!?。?
授權(quán)方法,是在shiro進(jìn)行鑒權(quán)的時候才能觸發(fā)。只是配置了authc/user/anon等,不會觸發(fā);
perms,port,rest,roles,ssl等,會觸發(fā)授權(quán)方法doGetAuthorizationInfo。
/**
* 清除所有緩存
*/
public void clearCachedAuth(){
this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
}
//清除ehcache中所有用戶權(quán)限緩存
RealmSecurityManager rsm = (RealmSecurityManager)SecurityUtils.getSecurityManager();
ShiroRealm authRealm = (ShiroRealm)rsm.getRealms().iterator().next();
authRealm.clearCachedAuth();
實際解決方案參考下文中的方案二!
在系統(tǒng)中,由管理員更改了用戶A信息后,如果用戶A在線,無法及時更新相關(guān)的改動;
更新用戶資料、權(quán)限等信息,如果該用戶在線,同步更新用戶信息解決方案:
在ShiroRealm中通過SessionDAO拿到所有在線的用戶,
Collection<Session> sessions = sessionDAO.getActiveSessions();
遍歷找到匹配的,根據(jù)情況,退出登錄或更新用戶信息:
@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))) {
//設(shè)置session立即失效,即將其踢出系統(tǒng)
session.setTimeout(0);
//TODO 或更新下用戶信息
break;
}
}
【不推薦理由】
用戶信息新增version版本標(biāo)記,寫個攔截器,每次請求判斷version是否一致,如有改動,根據(jù)情況,退出或更新用戶信息(本文統(tǒng)一做了退出登錄處理,可以結(jié)合實際需求做相應(yīng)調(diào)整)。
這個方案,基于樂觀鎖原理實現(xiàn)。同樣可解決動態(tài)更新用戶權(quán)限的問題。
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【詳見源碼】
/**
*
* @項目名稱:wyait-manage
* @類名稱:UserActionInterceptor
* @類描述:判斷用戶信息是否已被后臺更改,并根據(jù)更改的情況做對應(yīng)的處理
* @創(chuàng)建人:wyait
* @創(chuàng)建時間: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("請求到達(dá)后臺方法之前調(diào)用(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. 獲取數(shù)據(jù)庫中的用戶數(shù)據(jù)
User dataUser = this.userService.findUserByMobile(user.getMobile());
// 3. 對比session中用戶的version和數(shù)據(jù)庫中的是否一致
if (dataUser != null
&& null != dataUser.getVersion()
&& String.valueOf(user.getVersion()).equals(
String.valueOf(dataUser.getVersion()))) {
// 3.1 一樣,放行
return true;
}else{
// 3.2 不一樣,這里統(tǒng)一做退出登錄處理;//TODO 使用redis緩存用戶權(quán)限數(shù)據(jù),根據(jù)用戶更新、用戶權(quán)限更新;做對應(yīng)的處理。
SecurityUtils.getSubject().logout();
isAjaxResponse(request,response);
}
}
return false;
}
... ...
}
/**
*
* @項目名稱:wyait-manage
* @類名稱:MyWebMvcConfig
* @類描述:自定義靜態(tài)資源映射路徑和靜態(tài)資源存放路徑
* @創(chuàng)建人:wyait
* @修改時間:2018年5月3日09:55:23
* @version:
*/
@Configuration
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {
/**
* 添加攔截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 路徑根據(jù)后期項目的擴展,進(jìn)行調(diào)整
registry.addInterceptor(new UserActionInterceptor())
.addPathPatterns("/user/**", "/auth/**")
.excludePathPatterns("/user/sendMsg", "/user/login");
super.addInterceptors(registry);
}
}
錯誤信息:
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;
@Configuration
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {
/**
*
* @描述:在Spring添加攔截器之前先創(chuàng)建攔截器對象,這樣就能在Spring映射這個攔截器前,把攔截器中的依賴注入的對象給初始化完成了。
* </br>避免攔截器中注入的對象為null問題。
* @創(chuàng)建人:wyait
* @創(chuàng)建時間:2018年5月3日 上午10:07:36
* @return
*/
@Bean
public UserActionInterceptor userActionInterceptor(){
return new UserActionInterceptor();
}
/**
* 添加攔截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 路徑根據(jù)后期項目的擴展,進(jìn)行調(diào)整
registry.addInterceptor(userActionInterceptor())
.addPathPatterns("/user/**", "/auth/**")
.excludePathPatterns("/user/sendMsg", "/user/login");
super.addInterceptors(registry);
}
}
分布式或集群的時候,需要解決session共享問題;相關(guān)的方案有:session持久化、redis或其他中間件、nginx的ip_hash、cookie實現(xiàn)、服務(wù)器間Session同步等;這時候處理動態(tài)更新用戶信息,需要結(jié)合實際情況而定;
后期會更新redis版本。
linux 6.* 系統(tǒng)
jdk 1.7
tomcat 7.*
maven 3.3.3
五月 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啟動,會出現(xiàn)tomcat7和8版本沖突問題,本地解決了,線上依舊啟動不成功;再百度、google方案,大致是tomcat版本問題而打印的日志信息,按照搜索的方案配置,均未解決。
考慮應(yīng)該是環(huán)境配置的版本不一致導(dǎo)致的項目無法加載啟動成功,確認(rèn)并排查下開發(fā)、測試、線上的jdk、tomcat等版本是否一致。
java -version
jdk 1.8
java -v
jdk 1.7
這就是導(dǎo)致項目在linux系統(tǒng)啟動不起來的原因:開發(fā)和線上的jdk版本不一致?。?!
將windows的jdk版本切換為jdk1.7,重新打開新的dos窗口:java -version;jdk顯示為1.7.*。版本切換成功!
...
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.
1:compile (default-compile) on project wyait-manage: Fatal error compiling: 無效的
目標(biāo)發(fā)行版: 1.8 -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e swit
ch.
...
<!--
<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版本的配置;重新打包,成功!
開發(fā)過程中,要確保開發(fā)、測試、線上配置的環(huán)境(jdk、maven、tomcat等開發(fā)依賴的環(huán)境支持)保持一致。避免出現(xiàn)由于開發(fā)環(huán)境中的版本不一致而出現(xiàn)問題,導(dǎo)致項目上線出問題和延遲項目上線時間!
前篇:
后篇:
項目源碼:(包含數(shù)據(jù)庫源碼)
github源碼: https://github.com/wyait/manage.git
碼云:https://gitee.com/wyait/manage.git
github對應(yīng)項目源碼目錄:wyait-manage-1.2.0
碼云對應(yīng)項目源碼目錄:wyait-manage-1.2.0
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。