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;
    }
}

 

posted @ 2019-03-05 15:06  长途跋涉的孤狼  阅读(4474)  评论(0编辑  收藏  举报