摘要:關(guān)于的自動(dòng)對(duì)用戶對(duì)象序列化并加密當(dāng)獲得請(qǐng)求時(shí)能夠獲取反序列化且解密之后的用戶對(duì)象。
shirorememberMe流程原理研究
輸入用戶密碼正兒八經(jīng)登錄時(shí), 如果勾選了"記住我", 則后臺(tái)給shiro設(shè)置rememberme
前一次登錄勾選了記住我, 則本次登錄時(shí)isRemembered()==true(如果上一次設(shè)置了rememberme, 本次登錄是不會(huì)觸發(fā)action中的login()的方法的, 即會(huì)直接進(jìn)入登錄狀態(tài). 這里為了演示, 強(qiáng)行進(jìn)入login()方法).
經(jīng)過shiro的login()則表示為認(rèn)證登錄的. 就是說authentication==true. 訪問權(quán)限最高.
rememberMe==true, 則將不會(huì)進(jìn)入任何action. 可以訪問所有user控制的頁面或路徑. 但不能訪問authc控制的.
但是authentication=false. 這里有個(gè)關(guān)鍵點(diǎn):
subject.isAuthenticated()==true,
則subject.isRemembered()==false;
反之一樣
下圖所示, authentication=false, 并且能夠principle不為空, 能夠獲取用戶信息.
另外對(duì)于過濾器,一般這樣使用:
訪問一般網(wǎng)頁,如個(gè)人在主頁之類的,我們使用user攔截器即可,user攔截器只要用戶登錄(isRemembered()==true or isAuthenticated()==true)通過即可訪問成功;
訪問特殊網(wǎng)頁,如我的訂單,提交訂單頁面,我們使用authc攔截器即可,authc攔截器會(huì)判斷用戶是否是通過Subject.login(isAuthenticated()==true)登錄的,如果是才放行,否則會(huì)跳轉(zhuǎn)到登錄頁面叫你重新登錄。
關(guān)于rememberMe的cookieshiro自動(dòng)對(duì)用戶對(duì)象序列化并加密. 當(dāng)獲得請(qǐng)求時(shí), 能夠獲取反序列化且解密之后的用戶對(duì)象。
當(dāng)設(shè)置rememberMe==false, 將會(huì)自動(dòng)清空rememberMe cookie.
如下圖, 在設(shè)置rememberMe==false的前提下, 之前的rememberMe cookie已經(jīng)不見了.
項(xiàng)目重啟后(排除緩存影響). 強(qiáng)行訪問action, 能夠獲取user對(duì)象.
調(diào)用shiro的logout()方法, 即消除自動(dòng)登錄功能.
rememberMe功能實(shí)現(xiàn) 簡(jiǎn)單實(shí)現(xiàn)引入shiro框架
引入maven坐標(biāo).
org.apache.shiro shiro-all ${shiro.version}
配置spring
/css/**=anon /js/**=anon /images/**=anon /validatecode.jsp*=anon /userAction_login.action=anon /customerAction_login.action=anon /info.jsp*=anon /courierAction_pageQuery*=perms["courier:list"] /pages/base/courier.jsp*=perms["courier:list"] /** = user /pay/** = authc
實(shí)現(xiàn)上文配置文件中realm
public class UserRealm extends AuthorizingRealm { @Autowired private UserDao userDao; @Autowired private PermissionDao permissionDao; @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; // !這里的username可能并不是真正的username, 可能是手機(jī)號(hào)或者其他可以作為登錄憑證的字段! String username = token.getUsername(); User u = userDao.findByUsernameOrTelephone(username, username); if (u == null) { return null; } AuthenticationInfo info = new SimpleAuthenticationInfo(u, u.getPassword(), this.getName()); return info; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //獲取當(dāng)前用戶 User user = (User) principalCollection.getPrimaryPrincipal(); //內(nèi)置用戶:授予所有權(quán)限 Listpermissions = null; if (user != null && user.getUsername().equals("admin")) { permissions = permissionDao.findAll(); } else { // 其他普通用戶:查出該用戶對(duì)應(yīng)的所有權(quán)限 permissions = permissionDao.findByUserId(user.getId()); } // 授權(quán) SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); for (Permission p : permissions) { info.addStringPermission(p.getKeyword()); } return info; } }
登錄action
@Action(value = "userAction_login") public String login() throws UnsupportedEncodingException { Log.begin(); String validateCode_ser = (String) ServletActionContext.getRequest().getSession().getAttribute("validateCode"); Subject subject; if (StringUtils.isNotBlank(this.validateCode) && this.validateCode.equals(validateCode_ser)) { subject = SecurityUtils.getSubject(); // 不論用戶輸入的是用戶名還是手機(jī)號(hào), 前臺(tái)標(biāo)簽統(tǒng)一用username接收 UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword()); //[[ADD 2018-1-9 14:44:01 // 設(shè)置是否"記住我" rememberme = rememberme == null ? false : rememberme; //null=>false token.setRememberMe(rememberme); // ]] try { subject.login(token); if (rememberme) LOG.info("用戶【{}】自動(dòng)登錄----{}", "天王", String.valueOf(System.currentTimeMillis())); } catch (AuthenticationException e) { e.printStackTrace(); return LOGIN; } } else { this.addActionError("輸入的驗(yàn)證碼有誤!"); return ERROR; }//end if return "home"; }
注意: 默認(rèn)cookie會(huì)保存一年. 這個(gè)有點(diǎn)太長(zhǎng)了, 通常需要縮短.
主要是spring配置的區(qū)別, 需要: 1. 配置自定義cookie; 2. 注入給rememberMeManager; 3. 將rememberMeManager注入給securityManager.
復(fù)雜實(shí)現(xiàn)/css/**=anon /js/**=anon /images/**=anon /validatecode.jsp*=anon /userAction_login.action=anon /customerAction_login.action=anon /info.jsp*=anon /courierAction_pageQuery*=perms["courier:list"] /pages/base/courier.jsp*=perms["courier:list"] /** = user /pay/** = authc
這種方式需要在spring中配置很多參數(shù). 很繁瑣. 但是功能齊全. 如果只想實(shí)現(xiàn)簡(jiǎn)單的自動(dòng)功能, 可以參照簡(jiǎn)單實(shí)現(xiàn).
本部分spring配置可參見: 第十三章 RememberMe——《跟我學(xué)Shiro》
參考資料:
[1] http://jinnianshilongnian.ite...
[2] http://blog.icoolxue.com/shir...
[3] http://blog.csdn.net/lhacker/...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/68229.html
摘要:寫在前面在一款應(yīng)用的整個(gè)生命周期,我們都會(huì)談及該應(yīng)用的數(shù)據(jù)安全問題。用戶的合法性與數(shù)據(jù)的可見性是數(shù)據(jù)安全中非常重要的一部分。 寫在前面 在一款應(yīng)用的整個(gè)生命周期,我們都會(huì)談及該應(yīng)用的數(shù)據(jù)安全問題。用戶的合法性與數(shù)據(jù)的可見性是數(shù)據(jù)安全中非常重要的一部分。但是,一方面,不同的應(yīng)用對(duì)于數(shù)據(jù)的合法性和可見性要求的維度與粒度都有所區(qū)別;另一方面,以當(dāng)前微服務(wù)、多服務(wù)的架構(gòu)方式,如何共享Sessi...
JAVA單點(diǎn)登錄有好多種方式,譬如用cookie的domain做,用中間代理做等等,但都需要自行做許多開發(fā)工作。而其中耶魯大學(xué)的開源項(xiàng)目CAS提供了一個(gè)一站式解決方案,只需很少的擴(kuò)展即可輕松實(shí)現(xiàn)企業(yè)級(jí)單點(diǎn)登錄?;A(chǔ)知識(shí)網(wǎng)上其他挺多的,這里我就不詳述了。本文通過分析http請(qǐng)求過程中httpheader,cookie等數(shù)據(jù)剖析了cas(非代理模式,默認(rèn)驗(yàn)證邏輯。其他如restletAPI等可擴(kuò)展邏輯...
閱讀 2093·2023-04-25 17:57
閱讀 1293·2021-11-24 09:39
閱讀 2492·2019-08-29 16:39
閱讀 3321·2019-08-29 13:44
閱讀 3137·2019-08-29 13:14
閱讀 2328·2019-08-26 11:36
閱讀 3823·2019-08-26 11:00
閱讀 955·2019-08-26 10:14