web項目中用戶登錄的具體流程


一個登錄的具體流程:

1、前端發送公鑰的請求。

2、后台生產公鑰私鑰對,將公鑰返回前端,私鑰保存到session中。

3、前端拿到公鑰后,對用戶輸入的密碼進行md5加密,然后在對(md5加密后的密碼+密碼)進行rsa加密,發起登錄請求,將用戶名和加密后的密碼傳入后台進行校驗。

4、后台接受到加密后的密碼首先利用私鑰對密碼進行解密

5、對密碼進行完整的校驗即采用前32位的MD5碼與原始密碼(32位之后的值即為密碼)進行MD5加密后進行比較。

6、驗證通過后采用shiro的subject.login()將登陸驗證的工作轉交給shiro進行。

7、通過判斷shiro返回的異常信息來獲取校驗未成功的原因。

8、驗證通過檢查此用戶在其他地方時候登陸。方法為自定義一個session的緩存將登錄過的session與用戶名存入map中,從緩存中獲取此用戶名對應的緩存判斷sessionid是否一致,若不一致說明此次是重復登錄,將之前的session通過shiroSessionManager.getSessionDAO().delete(session)進行剔除。

9、返回登錄結果到前端。

具體代碼片段如下:

登錄校驗:

 1 public Result checkLogin(String username, String encryptPassword, RSAPrivateKey privateKey){
 2         
 3         String decryptPassword = "";
 4         if (privateKey != null && encryptPassword != null) {
 5             //解密后的密碼。由mds(pass) + pass 組成。
 6             decryptPassword = RSAUtils.decrypt(privateKey, encryptPassword);
 7         }
 8         if(decryptPassword.length() < 32){
 9             return Result.error("用戶名或密碼驗證失敗。");
10         }
11         //完整性校驗,防止篡改
12         if (!isComplate(decryptPassword)) {
13             return Result.error("密碼被篡改,驗證失敗。");
14         }
15         decryptPassword = decryptPassword.substring(32);
16         String password = new Sha256Hash(decryptPassword).toHex();
17         
18         //密碼完整性校驗通過,交給shiro進行驗證
19         //進行驗證,這里可以捕獲異常,然后返回對應信息
20         try{
21             Subject subject = SecurityUtils.getSubject();
22             UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
23             subject.login(usernamePasswordToken);
24             //剔除重復登錄的用戶
25             SessionsSecurityManager securityManager = (SessionsSecurityManager) SecurityUtils.getSecurityManager();
26             DefaultSessionManager shiroSessionManager = (DefaultSessionManager) securityManager.getSessionManager();
27             Session session = sessionManager.getSession(username);
28             if(session != null){
29                 //不是同一個會話,進行剔除
30                 if(!subject.getSession().getId().equals(session.getId())){
31                     shiroSessionManager.getSessionDAO().delete(session);
32                     sessionManager.removeSession(username);//緩存中移除
33                 }
34             }
35             //將新的用戶和session加入sessionManager中
36             sessionManager.addSession(username, subject.getSession());
37             
38         }catch(IncorrectCredentialsException ice){
39             return Result.error("用戶名或密碼驗證失敗");
40         }catch(UnknownAccountException uae){
41             return Result.error("賬號不存在");
42         }catch(LockedAccountException  uae){
43             return Result.error("賬號被鎖定"); 
44         }catch(ExcessiveAttemptsException  uae){
45             return Result.error("操作頻繁,請稍后再試");
46         }catch(ExpiredCredentialsException ece){
47             return Result.error("賬號已過期,請重新登錄");
48         }
49         return Result.ok();
50     }

UserManager

@Component
public class UserManager {
    
    @Autowired
    IFetchUser query;

    private ConcurrentMap<String, User> map = new ConcurrentHashMap<String, User>();
    
    public User getUser(String name){
        User user = map.get(name);
        if(user == null){
            //去庫中查詢
            user = query.queryFromDb(name);
            if(user != null){
                map.put(name, user);
            }
        }
        return user;
    }
    
    public void removeUser(String name){
        map.remove(name);
    }
}

 

Shiro的配置 

@Configuration
public class SysShiroConfiguration {

    
    @Bean
    public MemorySessionDAO memorySessionDAO(){
        MemorySessionDAO memorySessionDAO = new MemorySessionDAO();
        return memorySessionDAO;
    }
    
    @Bean
    public WebSessionManager webSessionManager(){
        DefaultWebSessionManager webSessionManager = new DefaultWebSessionManager();
        webSessionManager.setSessionDAO(memorySessionDAO());
        return webSessionManager;
    }
    
    @Bean
    public MemoryConstrainedCacheManager memoryConstrainedCacheManager(){
        MemoryConstrainedCacheManager cacheManager = new MemoryConstrainedCacheManager();
        return cacheManager;
    }
    
    //將自己的驗證方式加入容器
    @Bean
    public CustomShiroRealm customShiroRealm() {
        CustomShiroRealm customShiroRealm = new CustomShiroRealm();
        return customShiroRealm;
    }

    //權限管理,配置主要是Realm的管理認證
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(customShiroRealm());
        securityManager.setCacheManager(memoryConstrainedCacheManager());
        securityManager.setSessionManager(webSessionManager());
        return securityManager;
    }

    //Filter工廠,設置對應的過濾條件和跳轉條件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String,String> map = new HashMap<String, String>();
        //登出
//        map.put("/logout","logout");
//        map.put("/test/**","anon");
//        map.put("/pages/index.jsp","anon");
//        map.put("/index.jsp","anon");
//        map.put("/statics/**","anon");
        //對所有用戶認證
        map.put("/**","anon");
        //登錄
        shiroFilterFactoryBean.setLoginUrl("/login");
        //首頁
        shiroFilterFactoryBean.setSuccessUrl("/home");
        //錯誤頁面,認證不通過跳轉
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }
    
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    //加入注解的使用,不加入這個注解不生效
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM