spring引导:使用modelmapper和get-token将userdtoMap到userdetails

z0qdvdin  于 2021-06-26  发布在  Java
关注(0)|答案(0)|浏览(259)

我实现了一个自定义的安全功能和一个登录入口点:

@PostMapping("/login")
public ResponseEntity<UserRestResponseModel> userLogin(@RequestBody UserDetailsRequestModel userDetails) {
    if(userDetails.getEmail().isEmpty() || userDetails.getPassword().isEmpty()) {
        throw new UserServiceException(ErrorMessages.MISSING_REQUIRED_FIELD.getErrorMessage());
    }
    authenticate(userDetails.getEmail(), userDetails.getPassword());
    UserRestResponseModel userRestResponseModel = new UserRestResponseModel();

    ModelMapper modelMapper = new CustomMapper();
    //modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);

    UserDto loggedInUser = userService.getUser(userDetails.getEmail());
    if (loggedInUser == null)
        throw new UserServiceException("Error !!");

    if(loggedInUser.getIsAccountNonLocked() == Boolean.FALSE)
        throw new UserServiceException("User account is locked");

    userRestResponseModel = modelMapper.map(loggedInUser, UserRestResponseModel.class);
    UserPrincipal userPrincipal = modelMapper.map(loggedInUser, UserPrincipal.class);

    HttpHeaders jwtHeader = getJwtHeader(userPrincipal);

    ResponseEntity<UserRestResponseModel> returnValue =
            new ResponseEntity<>(userRestResponseModel, jwtHeader, HttpStatus.OK);

    return returnValue;
}
private void authenticate(String userName, String password) {
    authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userName, password));
}
private HttpHeaders getJwtHeader(UserPrincipal userPrincipal) {
    HttpHeaders headers = new HttpHeaders();
    String token = jwtTokenProvider.generateJwtToken(userPrincipal);
    headers.add(SecurityConstants.TOKEN_PREFIX, token);
    return headers;
}

我还实现了userprincipal类:

public class UserPrincipal implements UserDetails {
    private static final long serialVersionUID = 7464059818443209139L;

    private UserEntity userEntity;
    private String userKeyId;

    public UserPrincipal(){    }
    public UserPrincipal(UserEntity userEntity) {
        this.userEntity = userEntity;
        this.userKeyId = userEntity.getUserKeyId();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> authorities = new HashSet<>();
        Collection<AuthorityEntity> authorityEntities = new HashSet<>();
        // get user roles
        Collection<RoleEntity> roles = userEntity.getRoles();
        if (roles == null) {
            return authorities; // null
        }
        // get user roles
        roles.forEach((role) ->{
            authorities.add(new SimpleGrantedAuthority(role.getName()));
            authorityEntities.addAll(role.getAuthorities());
        });
        // get user authorities
        authorityEntities.forEach(authorityEntity ->
                authorities.add(
                        new SimpleGrantedAuthority(authorityEntity.getName())
                )
        );
        return authorities;
    }

    @Override
    public String getPassword() {
        return this.userEntity.getEncryptedPassword();
    }

    @Override
    public String getUsername() {
        return this.userEntity.getEmail();
    }

    @Override
    public boolean isAccountNonExpired() {
        return this.userEntity.getIsAccountNonExpired();
    }

我还有一个处理令牌的jwttokenprovider类。

@Component
public class JwtTokenProvider {
    public String generateJwtToken(UserPrincipal userPrincipal) {
        String[] claims = getClaimsFromUser(userPrincipal);
        return JWT.create()
                .withIssuer(SecurityConstants.TOKEN_ISSUER)
                .withAudience(SecurityConstants.TOKEN_AUDIENCE)
                .withIssuedAt(new Date())
                .withSubject(userPrincipal.getUsername())
                .withArrayClaim(SecurityConstants.AUTHORITIES, claims)
                .withExpiresAt(new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME))
                .sign(Algorithm.HMAC512(SecurityConstants.getTokenSecret().getBytes()));
    }

    public List<GrantedAuthority> getAuthorities(String token) {
        String[] claims = getClaimsFromToken(token);
        return stream(claims).map(SimpleGrantedAuthority::new).collect(Collectors.toList());
    }
    public Authentication getAuthentication(String userName,
                                            List<GrantedAuthority> authorities,
                                            HttpServletRequest request) {
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(userName, null, authorities);
        usernamePasswordAuthenticationToken.setDetails(
                new WebAuthenticationDetailsSource().buildDetails(request));
        return usernamePasswordAuthenticationToken;
    }

    public boolean isTokenValid(String userName, String token) {
        JWTVerifier verifier = getJWTVerifier();
        return StringUtils.isNotEmpty(userName) && !isTokenExpired(verifier, token);
    }

    public String getSubject(String token) {
        JWTVerifier jwtVerifier = getJWTVerifier();
        return jwtVerifier.verify(token).getSubject();

    }

    private boolean isTokenExpired(JWTVerifier verifier, String token) {
        Date expirationDate = verifier.verify(token).getExpiresAt();
        return expirationDate.before(new Date());
    }

    private String[] getClaimsFromToken(String token) {
        JWTVerifier verifier = getJWTVerifier();
        return verifier.verify(token).getClaim("Authorities").asArray(String.class);
    }
    private JWTVerifier getJWTVerifier() {
        JWTVerifier verifier;
        try {
            Algorithm algorithm = Algorithm.HMAC512(SecurityConstants.getTokenSecret());
            verifier = JWT.require(algorithm).withIssuer(SecurityConstants.TOKEN_ISSUER).build();
        } catch (JWTVerificationException e) {
            throw new JWTVerificationException(SecurityConstants.TOKEN_CANNOT_BE_VERIFIED);
        }
        return verifier;
    }
    private String[] getClaimsFromUser(UserPrincipal userPrincipal) {
        List<String> authorities = new ArrayList<>();
        for(GrantedAuthority grantedAuthority: userPrincipal.getAuthorities()) {
            authorities.add(grantedAuthority.getAuthority());
        }
        return authorities.toArray(new String[0]);
    }
}

一切正常,但我有2个问题:如果我没有一个无参数构造函数在我的userprincipal类,模型Map器返回一个错误。。。

"message": "An error occurred while processing the request ModelMapper mapping errors: Failed to instantiate instance of destination UserPrincipal. Ensure that UserPrincipal has a non-private no-argument constructor. 1 error".

如果我真的添加了一个无参数构造函数,我会有一个空指针异常(userprincipal为空)和一个很好的500错误。它让我发疯。
我的问题就在我的代码里:

UserDto loggedInUser = userService.getUser(userDetails.getEmail());
...
userRestResponseModel = modelMapper.map(loggedInUser, UserRestResponseModel.class);
UserPrincipal userPrincipal = modelMapper.map(loggedInUser, UserPrincipal.class);

HttpHeaders jwtHeader = getJwtHeader(userPrincipal);

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题