欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JsonWebToken工具结合切面token实现认证

程序员文章站 2022-05-03 12:24:55
...

 

 

权限校验的控制---1,直接用权限框架

                 2,用路径特征---不同的controller用不同的路径前缀---可根据这种特征用不同的权限认证

 

 

用JsonWebToken工具hash需要的字段之后生成一段字符串,之后这段字符串可以反向获取之前的明文----这个可以作为token--可以翻译出信息的token

 

用一个切面结合token实现认证:----尤其外部分享链接可以采用这种方式

 

1,认证

2,验证是否有效

 

有效期:每次请求之后无论成功失败都刷新,每次刷新都是重新生成claim除了用户名,密码,还是有事件戳,所以每次生成的不一样

 

 

   if (!tokenUtils.validateToken(token, user)) {

            log.info("{} : token validation fails", request.getServletPath());

            response.setStatus(HttpCodeEnum.FORBIDDEN.getCode());

            response.getWriter().print("Invalid token ");

            return false;

        }

 

/**

     * 根据 用户名、密码 验证 token

     *

     * @param token

     * @param username

     * @param password

     * @return

     */

    public Boolean validateToken(String token, String username, String password) {

        String tokenUsername = getUsername(token);

        String tokenPassword = getPassword(token);

        return (username.equals(tokenUsername) && password.equals(tokenPassword) && !(isExpired(token)));

    }

 

 

 

认证:

 @Override

    public User shareLogin(String token, UserLogin userLogin) throws NotFoundException, ServerException, UnAuthorizedExecption {

        //AES解密

        String decrypt = AESUtils.decrypt(token, null);

        //获取分享信息

        String tokenUserName = tokenUtils.getUsername(decrypt);

        String tokenPassword = tokenUtils.getPassword(decrypt);

 

        String[] tokenInfos = tokenUserName.split(Constants.SPLIT_CHAR_STRING);

        String[] tokenCrypts = tokenPassword.split(Constants.SPLIT_CHAR_STRING);

 

        if (tokenInfos.length < 2) {

            throw new ServerException("Invalid share token");

        }

 

        User loginUser = userMapper.selectByUsername(userLogin.getUsername());

        if (null == loginUser) {

            throw new NotFoundException("user is not found");

        }

 

        //校验密码

        if (!BCrypt.checkpw(userLogin.getPassword(), loginUser.getPassword())) {

            throw new ServerException("password is wrong");

        }

 

        Long shareUserId = Long.parseLong(tokenInfos[1]);

        if (shareUserId.longValue() < 1L) {

            throw new ServerException("Invalid share token");

        }

 

        User shareUser = userMapper.getById(shareUserId);

        if (null == shareUser) {

            throw new ServerException("Invalid share token");

        }

 

        if (tokenInfos.length == 3) {

            if (tokenCrypts.length < 2) {

                throw new ServerException("Invalid share token");

            }

            try {

                String sharedUserName = tokenInfos[2];

                Long sharedUserId = Long.parseLong(tokenCrypts[1]);

                if (!(loginUser.getUsername().equals(sharedUserName) && loginUser.getId().equals(sharedUserId)) && !loginUser.getId().equals(shareUserId)) {

                    throw new ForbiddenExecption("The resource requires authentication, which was not supplied with the request");

                }

            } catch (NumberFormatException e) {

                throw new ForbiddenExecption("The resource requires authentication, which was not supplied with the request");

            }

        }

 

        //是否激活

        if (!loginUser.getActive()) {

            throw new ServerException("this user is not active");

        }

 

        return loginUser;

    }

 

 

验证是否失效:

 

/**

     * 修改dashboard下的widget关联信息

     *

     * @param bindingResult

     * @param user

     * @param request

     * @return

     */

    @ApiOperation(value = "update dashboard widget relation")

    @PutMapping(value = "/{portalId}/dashboards/widgets", consumes = MediaType.APPLICATION_JSON_VALUE)

    public ResponseEntity updateMemDashboardWidget(@PathVariable("portalId") Long portalId,

                                                   @Valid @RequestBody MemDashboardWidgetDto[] memDashboardWidgets,

                                                   @ApiIgnore BindingResult bindingResult,

                                                   @ApiIgnore @CurrentUser User user,

                                                   HttpServletRequest request) {

        if (bindingResult.hasErrors()) {

            ResultMap resultMap = new ResultMap(tokenUtils).failAndRefreshToken(request).message(bindingResult.getFieldErrors().get(0).getDefaultMessage());

            return ResponseEntity.status(resultMap.getCode()).body(resultMap);

        }

 

        for (MemDashboardWidget memDashboardWidget : memDashboardWidgets) {

            if (invalidId(memDashboardWidget.getId())) {

                ResultMap resultMap = new ResultMap(tokenUtils).failAndRefreshToken(request).message("Invalid id");

                return ResponseEntity.status(resultMap.getCode()).body(resultMap);

            }

 

            if (invalidId(memDashboardWidget.getDashboardId())) {

                ResultMap resultMap = new ResultMap(tokenUtils).failAndRefreshToken(request).message("Invalid dashboard id");

                return ResponseEntity.status(resultMap.getCode()).body(resultMap);

            }

 

            if (invalidId(memDashboardWidget.getWidgetId())) {

                ResultMap resultMap = new ResultMap(tokenUtils).failAndRefreshToken(request).message("Invalid widget id");

                return ResponseEntity.status(resultMap.getCode()).body(resultMap);

            }

 

            if (memDashboardWidget.getPolling() && memDashboardWidget.getFrequency() < 1) {

                ResultMap resultMap = new ResultMap(tokenUtils).failAndRefreshToken(request).message("Invalid frequency");

                return ResponseEntity.status(resultMap.getCode()).body(resultMap);

            }

        }

 

        dashboardService.updateMemDashboardWidgets(portalId, user, memDashboardWidgets);

        return ResponseEntity.ok(new ResultMap(tokenUtils).successAndRefreshToken(request));

    }

 

 

 

 

 

生成token的时候如果需要使用过期时间,刷新也就是重新设置过期时间然后重新生成

可以不用过期时间,生成永久的token 

 

一般用于生成token的明文的对象是map类型

 

 /**

     * 根据 TokenDetail 实体生成Token

     *

     * @param tokenDetail

     * @return

     */

    public String generateToken(TokenDetail tokenDetail) {

        Map<String, Object> claims = new HashMap<String, Object>();

        claims.put(Consts.TOKEN_USER_NAME, StringUtils.isEmpty(tokenDetail.getUsername()) ? EMPTY : tokenDetail.getUsername());

        claims.put(Consts.TOKEN_USER_PASSWORD, StringUtils.isEmpty(tokenDetail.getPassword()) ? EMPTY : tokenDetail.getPassword());

        claims.put(Consts.TOKEN_CREATE_TIME, System.currentTimeMillis());

        return generate(claims);

    }

 

 

 /**

     * 根据 clams生成token

     *

     * @param claims

     * @return

     */

    private String generate(Map<String, Object> claims) {

        Long expiration = Long.parseLong(claims.get(Consts.TOKEN_CREATE_TIME) + EMPTY) + TIMEOUT;

        try {

            return Jwts.builder()

                    .setClaims(claims)

                    .setSubject(claims.get(Consts.TOKEN_USER_NAME).toString())

                    .setExpiration(new Date(expiration))

                    .signWith(null != SignatureAlgorithm.valueOf(ALGORITHM) ?

                            SignatureAlgorithm.valueOf(ALGORITHM) :

                            SignatureAlgorithm.HS512, SECRET.getBytes("UTF-8"))

                    .compact();

        } catch (UnsupportedEncodingException ex) {

            log.warn(ex.getMessage());

            return Jwts.builder()

                    .setClaims(claims)

                    .setSubject(claims.get(Consts.TOKEN_USER_NAME).toString())

                    .setExpiration(new Date(expiration))

                    .signWith(null != SignatureAlgorithm.valueOf(ALGORITHM) ?

                            SignatureAlgorithm.valueOf(ALGORITHM) :

                            SignatureAlgorithm.HS512, SECRET)

                    .compact();

        }

    }

 

 

 

 

解析token,生成claims对象,后续用这个对象获取相应的属性(明文)

 

 

/**

     * 获取token claims

     *

     * @param token

     * @return

     */

    private Claims getClaims(String token) {

        Claims claims;

        try {

            claims = Jwts.parser()

                    .setSigningKey(SECRET.getBytes("UTF-8"))

                    .parseClaimsJws(token.startsWith(Consts.TOKEN_PREFIX) ?

                            token.substring(token.indexOf(Consts.TOKEN_PREFIX) + Consts.TOKEN_PREFIX.length()).trim() :

                            token.trim())

                    .getBody();

        } catch (Exception e) {

            log.warn(e.getMessage());

            claims = Jwts.parser()

                    .setSigningKey(SECRET)

                    .parseClaimsJws(token.startsWith(Consts.TOKEN_PREFIX) ?

                            token.substring(token.indexOf(Consts.TOKEN_PREFIX) + Consts.TOKEN_PREFIX.length()).trim() :

                            token.trim())

                    .getBody();

        }

        return claims;

    }

 

 

 

 

 /**

     * 解析 token 用户名

     *

     * @param token

     * @return

     */

    public String getUsername(String token) {

        String username;

        try {

            final Claims claims = getClaims(token);

            username = claims.get(Consts.TOKEN_USER_NAME).toString();

        } catch (Exception e) {

            username = null;

        }

        return username;

    }

 

 

 

 

 

相关标签: 架构