栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

【Java从零到架构师第③季】【49】会话管理—Token

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Java从零到架构师第③季】【49】会话管理—Token


持续学习&持续更新中…

守破离


【Java从零到架构师第③季】【49】会话管理—Token_ehcache
  • 基于Cookie、Session
  • 基于Token
  • ehcache
    • 简单使用
    • 项目使用:登录、登出
  • 补充:简单的分布式架构介绍
  • 参考

基于Cookie、Session

基于Token

ehcache 简单使用

依赖:

	
	
	    org.ehcache
	    ehcache
	

标签:

    
    
    
        
            
            
            
            
            
            
        
        
            
            
            1000 
            
            
        
    

使用:




    
        java.lang.Object
        java.lang.Object
        
            10000
        
    

    

    
    
        
            7
        
    

    
    
        
            
        
    

public class Caches {
    private static final CacheManager MGR;
    private static final Cache DEFAULT_CACHE;
    private static final Cache TOKEN_CACHE;
    static {
        // 初始化缓存管理器
        URL url = Caches.class.getClassLoader().getResource("ehcache.xml");
        assert url != null;
        Configuration cfg = new XmlConfiguration(url);
        MGR = CacheManagerBuilder.newCacheManager(cfg);
        MGR.init();

        // 缓存对象
        DEFAULT_CACHE = MGR.getCache("default", Object.class, Object.class);
        TOKEN_CACHE = MGR.getCache("token", Object.class, Object.class);
    }

    public static void put(Object key, Object value) {
        if (key == null || value == null) return;
        DEFAULT_CACHE.put(key, value);
    }

    public static void remove(Object key) {
        if (key == null) return;
        DEFAULT_CACHE.remove(key);
    }

    public static  T get(Object key) {
        if (key == null) return null;
        return (T) DEFAULT_CACHE.get(key);
    }

    public static void clear() {
        DEFAULT_CACHE.clear();
    }

    public static void putToken(Object key, Object value) {
        if (key == null || value == null) return;
        TOKEN_CACHE.put(key, value);
    }

    public static void removeToken(Object key) {
        if (key == null) return;
        TOKEN_CACHE.remove(key);
    }

    public static  T getToken(Object key) {
        if (key == null) return null;
        return (T) TOKEN_CACHE.get(key);
    }

    public static void clearToken() {
        TOKEN_CACHE.clear();
    }
}
项目使用:登录、登出
  • 只要近7天登录过,就不会失效,就不用重新登录



    
        java.lang.Object
        java.lang.Object
        
            10000
        
    

    

    
    
        
            7

        
        
            
                programmer.lp.jk.common.cache.TokenCacheListener
                
                ASYNCHRONOUS
                
                UNORDERED
                
                CREATED
                EXPIRED
                REMOVED
            
        
    

    
    
        
            
        
    

public class TokenCacheListener implements CacheEventListener {
    @Override
    public void onEvent(CacheEvent cacheEvent) {
        String token = (String) cacheEvent.getKey();
        switch (cacheEvent.getType()) {
            case CREATED: {// 添加了一个新的token(说明有一个用户刚登录)
                SysUserDto user = (SysUserDto) cacheEvent.getNewValue();
                // 以便将来通过用户id找到他对应的token
                Caches.put(user.getUser().getId(), token);
                break;
            }

            case EXPIRED:
            case REMOVED: { // token被移除或者过期了
                SysUserDto user = (SysUserDto) cacheEvent.getOldValue();
                Caches.remove(user.getUser().getId());
                break;
            }

            default: break;
        }
    }
}
@Override
    public RespLogin login(ReqLogin reqVo) {
        // 根据用户名查询用户
        MPLambdaQueryWrapper wrapper = new MPLambdaQueryWrapper<>();
        wrapper.eq(SysUser::getUsername, reqVo.getUsername());
        SysUser po = baseMapper.selectOne(wrapper);

        // 用户名不存在
        if (po == null) {
            return JSONResults.exception(CodeMsg.WRONG_USERNAME);
        }

        // 密码不正确
        if (!po.getPassword().equals(reqVo.getPassword())) {
            return JSONResults.exception(CodeMsg.WRONG_PASSWORD);
        }

        // 账号锁定
        if (po.getStatus() == Constants.SysUserStatus.LOCKED) {
            return JSONResults.exception(CodeMsg.USER_LOCKED);
        }

        

        // 更新登录时间
        po.setLoginTime(new Date());
        baseMapper.updateById(po);

        SysUserDto dto = new SysUserDto();
        dto.setUser(po);
        // 根据用户id查询所有的角色:sys_role,sys_user_role
        List roles = roleService.listByUserId(po.getId());

        // 根据角色id查询所有的资源:sys_resource、sys_role_resource
        if (!CollectionUtils.isEmpty(roles)) {
            dto.setRoles(roles);

            List roleIds = Streams.map(roles, SysRole::getId);
            List resources = resourceService.listByRoleIds(roleIds);
            dto.setResources(resources);
        }

        // 生成Token,发送Token给用户
        String token = UUID.randomUUID().toString();
        // 存储token到缓存中
        Caches.putToken(token, dto);

        // 返回给客户端的具体数据
        RespLogin vo = MapStruct.INSTANCE.po2loginVo(po);
        vo.setToken(token);
        return vo;
    }
    @PostMapping("/logout")
    @ApiOperation("退出登录")
    public JSONResult logout(@RequestHeader(TokenFilter.HEADER_TOKEN) String token) {
        Caches.removeToken(token);
        return JSONResults.ok(CodeMsg.LOGOUT_OK);
    }
    @Override
    public boolean saveOrUpdate(ReqSaveSysUser entity) {
        // 转成PO
        SysUser po = MapStruct.INSTANCE.vo2po(entity);

        // 保存用户信息
        if (!saveOrUpdate(po)) return false;

        Integer id = entity.getId();
        if (id != null && id > 0) {// 如果是做更新
            // 将更新成功的用户从缓存中移除(让token失效,用户必须重新登录)
            Caches.removeToken(Caches.get(id));
//            Caches.remove(id);
            // 删除当前用户的所有角色信息
            userRoleService.removeByUserId(entity.getId());
        }

        // 保存角色信息
        String roleIdsStr = entity.getRoleIds();
        if (Strings.isEmpty(roleIdsStr)) return true;

        String[] roleIds = roleIdsStr.split(",");
        List userRoles = new ArrayList<>();
        Integer userId = po.getId();
        for (String roleId : roleIds) { // 构建SysUserRole对象
            SysUserRole userRole = new SysUserRole();
            userRole.setUserId(userId);
            userRole.setRoleId(Short.parseShort(roleId));
            userRoles.add(userRole);
        }
        return userRoleService.saveBatch(userRoles);
    }
// 角色信息被更新了也要让用户重新登录.
// 重新登录是为了去查用户的权限(资源),让其配合Shiro使用
    @Override
    public boolean saveOrUpdate(ReqSaveSysRole entity) {
        // 转成PO
        SysRole po = MapStruct.INSTANCE.vo2po(entity);

        // 保存角色信息
        if (!saveOrUpdate(po)) return false;

        Short id = entity.getId();
        if (id != null && id > 0) {
            MPLambdaQueryWrapper wrapper = new MPLambdaQueryWrapper<>();
            wrapper.select(SysUserRole::getUserId);
            wrapper.eq(SysUserRole::getRoleId, id);
            List userIds = userRoleMapper.selectObjs(wrapper);
            if (!CollectionUtils.isEmpty(userIds)) {
                for (Object userId : userIds) {
                    // 将拥有这个角色的用户从缓存中移除(让token失效,用户必须重新登录)
                    Caches.removeToken(Caches.get(userId));
                }
            }

            // 删除当前角色的所有资源信息
            roleResourceService.removeByRoleId(id);
        }

        // 保存角色信息
        String resourceIdsStr = entity.getResourceIds();
        if (Strings.isEmpty(resourceIdsStr)) return true;

        String[] resourceIds = resourceIdsStr.split(",");
        List roleResources = new ArrayList<>();
        Short roleId = po.getId();
        for (String resourceId : resourceIds) { // 构建SysUserRole对象
            SysRoleResource roleResource = new SysRoleResource();
            roleResource.setRoleId(roleId);
            roleResource.setResourceId(Short.parseShort(resourceId));
            roleResources.add(roleResource);
        }
        return roleResourceService.saveBatch(roleResources);
    }
 
补充:简单的分布式架构介绍 

参考

小码哥-李明杰: Java从0到架构师③进阶互联网架构师.


本文完,感谢您的关注支持!


转载请注明:文章转载自 www.wk8.com.cn
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号