SpringSecurity验证流程解析

SpringSecurity

  1. TokenAuthenticationFilter

    if (httpRequest.getServletPath().equals(loginLink)) {
        //如果是登录或注销的话,设置不沿着过滤器向下
        doNotContinueWithRequestProcessing(httpRequest);
        checkLoginAnDoSomething(httpRequest, httpResponse, token);
    }
    
  2. checkLoginAnDoSomething(httpRequest, httpResponse, token);

    example: Authorization=Basic YWRtaW46MTIzNDU2 (admin:123456)
    
    private boolean checkLoginAnDoSomething(HttpServletRequest httpRequest, HttpServletResponse httpResponse,
        String token) throws IOException {
        String authorization = httpRequest.getHeader(CacheConstant.AUTHORIZATION);
        ReturnStatus result = null;
        if (authorization != null) {
            result = checkBasicAuthorization(authorization, httpRequest, httpResponse, token);
        }
    
        if (null == result) {
            result = new ReturnStatus(false);
            result.getErrors().add(new MError(MErrorCode.e9000));
            result.setMessage(MErrorCode.e9000.desc());
        }
    
        String body;
        try {
            body = JsonUtils.toJson(result);// JsonParserFactory.getParser().toJson(result).toString();
            httpResponse.setContentType("text/html;charset=UTF-8");
            httpResponse.getWriter().write(body);
        } catch (Exception e) {
            throw new IOException(e);
        }
    
        return result.isSuccess();
    

    }

  3. checkBasicAuthorization(authorization, httpRequest, httpResponse, token);

    private ReturnStatus checkBasicAuthorization(String authorization, HttpServletRequest httpRequest,
            HttpServletResponse httpResponse, String token) throws IOException {
        StringTokenizer tokenizer = new StringTokenizer(authorization);
        if (tokenizer.countTokens() < 2) {
            return null;
        }
        if (!tokenizer.nextToken().equalsIgnoreCase(CacheConstant.BASIC_AUTH_PREFIX)) {
            return null;
        }
    
        String base64 = tokenizer.nextToken();
        String loginPassword = new String(Base64.decode(base64.getBytes(StandardCharsets.UTF_8)));
        tokenizer = new StringTokenizer(loginPassword, ":");
        String username = tokenizer.nextToken();
        String pwd = tokenizer.nextToken();
        String password = passwordEncoder.encodePassword(pwd, null);
        ReturnStatus status = checkUsernameAndPassword(username, password, httpRequest, httpResponse, token);
        // 登录成功后返回登录状态
        return status;
    }
    
  4. private ReturnStatus checkUsernameAndPassword(String username, String password, HttpServletRequest httpRequest,HttpServletResponse httpResponse, String oldtoken)

    private ReturnStatus checkUsernameAndPassword(String username, String password, HttpServletRequest httpRequest,
            HttpServletResponse httpResponse, String oldtoken) throws IOException {
        ReturnStatus returnResult = new ReturnStatus(false);
        TokenInfo tokenInfo = authenticationService.authenticate(username, password, httpRequest);
        if (tokenInfo != null && tokenInfo.getUserDetails() != null) {
            VerifyContext verifyContext = (VerifyContext) tokenInfo.getUserDetails();
            Account account = (Account) verifyContext.getUser().getEntity();
            if (account.isLogin()) {
                if (null != oldtoken && !"".equals(oldtoken) && !"null".equals(oldtoken)
                        && !"undefined".equals(oldtoken)) {
                    logger.info("tokenInfo.setToken use the oldtoken Token :{}", tokenInfo.getToken());
                    tokenInfo.setToken(oldtoken);
                }
                logger.info("the new Token :{},entity:{}", tokenInfo.getToken(), tokenInfo);
                this.cacheManager.saveObject(CacheEnum.TOKEN, tokenInfo.getToken(), tokenInfo.getUserDetails(),
                        CacheConstant.USER_SESSION_TIME);
                logger.info("the token:{}, save object:{}", tokenInfo.getToken(),
                        this.cacheManager.getObject(CacheEnum.TOKEN, tokenInfo.getToken()));
                returnResult.setEntity(account);
                returnResult.setSuccess(true);
            } else {
                returnResult.getErrors().add(new MError(MErrorCode.e9001));
                returnResult.setMessage(MErrorCode.e9001.desc());
            }
            httpResponse.setHeader(CacheConstant.HEADER_TOKEN, tokenInfo.getToken());
        } else {
            logger.error("User {} ,Password {} Unauthorized!", username, password);
            returnResult.getErrors().add(new MError(MErrorCode.e9000));
            returnResult.setMessage(MErrorCode.e9000.desc());
        }
        return returnResult;
    }
    

基于用户-角色-权限设计

Account

accountName//账号名
accountPwd//密码
status//状态
accountType//账号类型
entityID//实体id
lastLoginTime//最后一次登录时间
loginTimes//登录次数
roleIds//角色列表
//一个账号可以关联角色,角色呈树状结构,可多选

Function

name//功能点名称
parentId//父级
memo//描述
action//资源url
order//排序
icon//图标
permissionCode//唯一权限标识
permissionName//权限名称

Role

name//角色名称
parentId//父级
memo//描述
functionIds//功能点
order//排序
//角色也是呈树状菜单的,角色里面有权限配置,所有的功能点以树状结构展示,通过角色去关联功能点

递归菜单和角色

// 获取标准JSON数据
public static List<Map<String, Object>> getStandardJSON() {
    // 根据不同框架获取对应的List数据
    List<Map<String, Object>> queryList = query.find();
    List<Map<String, Object>> parentList = Lists.newArrayList();
    for (Map<String, Object> map : queryList) {
        if (map.get("pId").equals("0")) {
            parentList.add(map);
        }
    }    
    recursionChildren(parentList, queryList);
    return parentList;
}

// 递归获取子节点数据
public static void recursionChildren (List<Map<String, Object>> parentList, 
List<Map<String, Object>> allList) {
    for (Map<String, Object> parentMap : parentList) {
        List<Map<String, Object>> childrenList = Lists.newArrayList();
        for (Map<String, Object> allMap : allList) {
            if (allMap.get("pId").equals(parentMap.get("id"))) {
                childrenList.add(allMap);
            }
        }
        if (!ParamValidUtils.isEmpty(childrenList)) {
            parentMap.put("children", childrenList);
            recursionChildren(childrenList, allList);
        }
    }
}