@Override
    protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken authenticationToken) {
        String token = (String) authenticationToken.getCredentials();
        if (StringUtils.isEmpty(token)) {
            return null;
        }

        String userName = JwtUtils.getIssuer(token);
        if (StringUtils.isEmpty(userName)) {
            throw new AuthenticationException("userName is null");
        }

        DashboardUserVO dashboardUserVO = dashboardUserService.findByUserName(userName);
        if (Objects.isNull(dashboardUserVO)) {
            throw new AuthenticationException(String.format("userName(%s) can not be found.", userName));
        }

        String clientIdFromToken = JwtUtils.getClientId(token);
        if (StringUtils.isNotEmpty(dashboardUserVO.getClientId()) && !StringUtils.equals(dashboardUserVO.getClientId(), clientIdFromToken)) {
            throw new AuthenticationException("clientId is invalid or does not match");
        }

        if (!JwtUtils.verifyToken(token, dashboardUserVO.getPassword())) {
            throw new AuthenticationException("token is error.");
        }

        return new SimpleAuthenticationInfo(UserInfo.builder()
                .userName(userName)
                .userId(dashboardUserVO.getId())
                .build(), token, this.getName());
    }
@Test
    public void testDoGetAuthenticationInfo() {
        final AuthenticationToken token = mock(AuthenticationToken.class);
        final DashboardUserVO dashboardUserVO = mock(DashboardUserVO.class);

        when(token.getCredentials()).thenReturn(null);
        assertNull(shiroRealm.doGetAuthenticationInfo(token));

        AuthenticationException exception1 = assertThrows(AuthenticationException.class, () -> {
            when(token.getCredentials()).thenReturn("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
                    + ".eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ"
                    + ".cThIIoDvwdueQB468K5xDc5633seEFoqwxjF_xSJyQQ");
            shiroRealm.doGetAuthenticationInfo(token);
        });
        assertNotNull(exception1);

        AuthenticationException exception2 = assertThrows(AuthenticationException.class, () -> {
            when(dashboardUserService.findByUserName(any())).thenReturn(null);
            when(token.getCredentials()).thenReturn("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
                    + ".eyJzdWIiOiIxMjM0NTY3ODkwIiwidXNlck5hbWUiOiJKb2huIERvZSIsImlhdCI6MTUxNjIzOTAyMn0"
                    + ".vZiLpzbncmNC5KL1idgfapCOTsRC0h_5XnqxaGfcLlM");
            shiroRealm.doGetAuthenticationInfo(token);
        });
        assertNotNull(exception2);

        AuthenticationException exception3 = assertThrows(AuthenticationException.class, () -> {
            when(dashboardUserService.findByUserName(any())).thenReturn(dashboardUserVO);
            when(dashboardUserVO.getPassword()).thenReturn(PASSWORD);
            when(token.getCredentials()).thenReturn("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
                    + ".eyJzdWIiOiIxMjM0NTY3ODkwIiwidXNlck5hbWUiOiJKb2huIERvZSIsImlhdCI6MTUxNjIzOTAyMn0"
                    + ".vZiLpzbncmNC5KL1idgfapCOTsRC0h_5XnqxaGfcLlM");
            shiroRealm.doGetAuthenticationInfo(token);
        });
        assertNotNull(exception3);

        when(dashboardUserService.findByUserName(any())).thenReturn(dashboardUserVO);
        when(dashboardUserVO.getPassword()).thenReturn(PASSWORD);
        when(token.getCredentials()).thenReturn("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
                + ".eyJzdWIiOiIxMjM0NTY3ODkwIiwidXNlck5hbWUiOiJKb2huIERvZSIsImlhdCI6MTUxNjIzOTAyMn0"
                + ".Qlpf6FdKAffgceukbi2BQYdPVf71d4Nwy0YQlkiTQFc");
        AuthenticationInfo info = shiroRealm.doGetAuthenticationInfo(token);
        assertNotNull(info);
    }