InvalidDefinitionException: невозможно создать экземпляр org.springframework.security.core.GrantedAuthority. - PullRequest
0 голосов
/ 05 августа 2020

У меня проблемы с моим пользовательским классом, точнее с grantedAuthority, похоже, и я не могу найти решение для него.

Вот мой пользовательский класс, который реализует userdetails :

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;


import com.example.demo.domain.security.Authority;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

@Entity
@Table(name="user")
public class User implements UserDetails, Serializable{
    
    private static final long serialVersionUID = 784154L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long userId;
    
    
    @JsonIgnore
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<Account> accounts;
    
    @JsonIgnore
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<Transaction> transactions;
    
    private String firstName;
    private String lastName;
    
    @Column(name="region")
    private String region;
    
    private String email;
    private String username;
    private String password; 
    private boolean status = true; 
    

    @ManyToOne(fetch=FetchType.EAGER,cascade={CascadeType.ALL})
    private  Role role;
    
    
    public User() {
    }
    
    @JsonCreator
    public User( @JsonProperty Long userId, @JsonProperty Set<Account> accounts,
            @JsonProperty Set<Transaction> transactions,    @JsonProperty String firstname,
            @JsonProperty String lastname,  @JsonProperty String region,
            @JsonProperty String email, @JsonProperty String username,  @JsonProperty String password,
            @JsonProperty boolean status, @JsonProperty Role role) {
        
    }

    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public boolean getStatus(){
        return this.status;
    }
    public void setStatus(boolean enabled) {
        this.status = enabled;
    }

    public Role getRole() {
        return role;
    }
    public void setRole(Role role) {
        this.role = role;
    }
    
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    
    public Set<Account> getAccounts() {
        return accounts;
    }
    public void setAccounts(Set<Account> accounts) {
        this.accounts = accounts;
    }

    public Long getUserId() {
        return userId;
    }
    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    

    public String getRegion() {
        return region;
    }
    public void setRegion(String region) {
        this.region = region;
    }
    
    public Set<Transaction> getTransactions() {
        return transactions;
    }
    public void setTransactions(Set<Transaction> transactions) {
        this.transactions = transactions;
    }
    
    @JsonDeserialize
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        // TODO Auto-generated method stub
        Set<GrantedAuthority> authorities = new HashSet<>(); 
         authorities.add(  new Authority(role.getType()));
        
        return authorities;
    }
    
    @Override
    public boolean isAccountNonExpired() {
        // TODO Auto-generated method stub
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        // TODO Auto-generated method stub
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        // TODO Auto-generated method stub
        return true;
    } 
    
    @Override
    public boolean isEnabled() {
        return status;
    }
}

Это мой класс пользовательского контроллера:

package com.example.demo.controller;
import java.security.Principal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;
import javax.websocket.server.PathParam;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.config.SecurityConfig;
import com.example.demo.config.SecurityUtility;
import com.example.demo.entities.Role;
import com.example.demo.entities.User;
import com.example.demo.enumerates.UserRole;
import com.example.demo.repositories.RoleRepo;
import com.example.demo.services.UserService;
import com.example.demo.utility.MailConstructor;

@RestController
//@CrossOrigin(origins = "*", allowedHeaders = "*")
@CrossOrigin("*")
@RequestMapping("/user")
public class UserController {
    
    @Autowired
    private UserService userS;
    
    @Autowired
    private RoleRepo roleRepository;
    
    @GetMapping("/list")
    public List<User> getAllUsers(){
        return userS.findAll(); 
    }
    
    @GetMapping("/role/list")
    public List<Role> getRoleList(){
        return userS.findRoles();
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable(value = "id") Long User_id) {
        User User = userS.findOne(User_id);
         return ResponseEntity.ok().body(User);
    }

     @PutMapping("/Users/{id}")
        public ResponseEntity<User> updateUser(@PathVariable(value = "id") Long User_id, @RequestBody User UserDetails){
            User User = userS.findOne(User_id);
            User.setFirstName(UserDetails.getFirstName());
            final User updatedUser = userS.save(User);
            return ResponseEntity.ok(updatedUser);
 }
     
     @DeleteMapping("/Users/{id}")
        public Map<String, Boolean> deleteUser(@PathVariable(value = "id") Long User_id){
            User User = userS.findOne(User_id);
            userS.delete(User);
            Map<String, Boolean> response = new HashMap<>();
            response.put("deleted", Boolean.TRUE);
            return response;
        }
        
        @PutMapping("/updateUser/{idR}")
        public ResponseEntity userUpdate(
                @RequestBody User user,
                @PathVariable("idR") Long idR
                )throws Exception{
            long id = user.getUserId();
            System.out.println("je suis ici");
            String username = user.getUsername();
            String region = null;
            
            boolean status = user.getStatus();
            System.out.println(status);
            
            
            
           user = userS.findById(id);
            
            if(userS.findByUsername(username) != null){
                if(userS.findByUsername(username).getUserId() != user.getUserId()){
                    return new ResponseEntity("Username not found!", HttpStatus.BAD_REQUEST);
                }
            }   
            
            user.setRegion(region);
            
            if(status==true)    
                user.setStatus(true);
            else
                user.setStatus(false);
            Optional<Role> Optrole= roleRepository.findById(idR);
            Role role = Optrole.get();
            System.out.println(idR);
            userS.addRoleToUser(username, role.getType());
            
            userS.save(user);
            
            return new ResponseEntity("User updated successfully!", HttpStatus.OK);
        }
        
        @PostMapping("/updateUserInfo")
        public ResponseEntity profileInfo(
                @RequestBody HashMap<String, Object> mapper
                )throws Exception{
            int id = (Integer) mapper.get("id"); 
            String email = (String) mapper.get("email");
            String region = (String) mapper.get("userRegion");
            String username = (String) mapper.get("username");
            String firstName = (String) mapper.get("firstName"); 
            String lastName = (String) mapper.get("lastName"); 
            String newPassword = (String) mapper.get("newPassword"); 
            String currentPassword = (String) mapper.get("currentPassword"); 
        
            User currentUser = userS.findById(Long.valueOf(id));
            
            if(currentUser == null){
                return new ResponseEntity("User not found!", HttpStatus.BAD_REQUEST);
            }
            
            if(userS.findByEmail(email) != null){
                if(userS.findByEmail(email).getUserId() != currentUser.getUserId()){
                    return new ResponseEntity("Email not found!", HttpStatus.BAD_REQUEST);
                }
            }
            
            if(userS.findByUsername(username) != null){
                if(userS.findByUsername(username).getUserId() != currentUser.getUserId()){
                    return new ResponseEntity("Username not found!", HttpStatus.BAD_REQUEST);
                }
            }
            
            SecurityConfig securityConfig = new SecurityConfig();
            if(newPassword != null && !newPassword.isEmpty() && !newPassword.equals("")){
                BCryptPasswordEncoder passwordEncoder = SecurityUtility.passwordEncoder();
                String dbPassword = currentUser.getPassword(); 
                if(currentPassword.equals(dbPassword)){
                    currentUser.setPassword(passwordEncoder.encode(newPassword));
                }else{
                    return new ResponseEntity("Current Password Incorrect!", HttpStatus.BAD_REQUEST);
                }
            }
            
            currentUser.setFirstName(firstName);
            currentUser.setLastName(lastName);
            currentUser.setEmail(email);
            currentUser.setUsername(username);
            currentUser.setRegion(region);      
            
            userS.save(currentUser);
            
            //System.out.println("username "+ currentUser.getUsername());
            
            return new ResponseEntity("User updated successfully!", HttpStatus.OK);         
        }
        
        @GetMapping("/getCurrentUser")
        @ResponseBody
        public User getCurrentUser(Principal principal){
            //String name = SecurityContextHolder.getContext().getAuthentication().getName();
        
            User user = userS.findByUsername(principal.getName());
            System.out.println(user.getFirstName());
            return user;
        }
        
        @Autowired
        private MailConstructor mailConstructor; 
        
        @Autowired
        private JavaMailSender mailSender; 
        
        @PostMapping("/newUser/{idR}")
        public ResponseEntity newUserPost(
                @RequestBody User user,
                @PathVariable(name = "idR", required = false) Long idR
                )throws Exception{  
            
        
               // long id = user.getUserId();
                String username = user.getFirstName()+user.getLastName();
                user.setUsername(username);
                String userEmail = user.getEmail();
                System.out.println("id role is "+idR);
                Optional <Role> Optrole= roleRepository.findById(idR);
                Role role = Optrole.get();
                Role r = role;
                user.setRole(r);
                UserRole roleName = r.getType();
                System.out.println(roleName);
                
                //mapper.forEach((key, value) ->
                System.out.println(user.getUsername());
                
                if(userS.findByUsername(username) != null){
                    return new ResponseEntity("username Exists", HttpStatus.BAD_REQUEST);
                }
                
                if(userS.findByEmail(userEmail) != null){
                    return new ResponseEntity("Email Exists", HttpStatus.BAD_REQUEST);  
                }
                
                String password = SecurityUtility.randomPassword();
                
                String encryptedPassword = SecurityUtility.passwordEncoder().encode(password);
                user.setPassword(encryptedPassword);
                
                userS.save(user);
                userS.addRoleToUser(username,roleName);
                
                SimpleMailMessage email = mailConstructor.constructNewUserEmail(user, password); 
                mailSender.send(email);
                
                return new ResponseEntity("User Added Successfully!", HttpStatus.OK);
        }
        
        @PostMapping("/forgetPassword")
        public ResponseEntity forgetPasswordPost(
                HttpServletRequest request,
                @RequestBody HashMap<String, String> mapper) throws Exception{
            User user = userS.findByEmail(mapper.get("email"));

        if (user == null){
        return new ResponseEntity ("Email not found ", HttpStatus.BAD_REQUEST);
        }

        String password = SecurityUtility.randomPassword();

        String encryptedPassword = SecurityUtility.passwordEncoder().encode(password);
        user.setPassword(encryptedPassword);
        userS.save(user);

        SimpleMailMessage newEmail = mailConstructor.constructForgetPasswordEmail(user, password);

        mailSender.send(newEmail);

        return new ResponseEntity ("Email sent!", HttpStatus.OK);
    }
}

Я пытаюсь обновить своего пользователя, чтобы установить новый регион, и получаю эту ошибку:

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.springframework.security.core.GrantedAuthority` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
 at [Source: (PushbackInputStream); line: 1, column: 359] (through reference chain: com.example.demo.entities.Account["user"]->com.example.demo.entities.User["authorities"]->java.util.ArrayList[0])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1611)
    at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1077)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:265)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:285)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:542)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:535)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:451)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1310)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:331)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:164)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:371)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:164)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4482)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3487)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:269)

и это мой интерфейс, где я вызываю свои функции из бэкенда

import { Injectable } from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import { Observable } from 'rxjs';
import {User} from '../models/user';
@Injectable({
  providedIn: 'root'
})
export class UserService {
  private baseUrl = 'http://localhost:8888/user';
  user : User = new User();
  constructor(private http: HttpClient) { }
  getUser(id: number): Observable<any> {
    const headers = new HttpHeaders({Authorization: 'Basic ' + localStorage.getItem('token')});
    return this.http.get(`${this.baseUrl}/${id}`,{headers});
  }
  // tslint:disable-next-line:ban-types
  createUser(user: User,roleid : number): Observable<Object> {
    const headers = new HttpHeaders({Authorization: 'Basic ' + localStorage.getItem('token')});
    console.log(localStorage.getItem('token'))
    return this.http.post(`${this.baseUrl}/newUser/${roleid}`, user,{headers});
  }
  getUserList(): Observable<any> {
    const headers = new HttpHeaders({Authorization: 'Basic ' + localStorage.getItem('token')});
    return this.http.get(`${this.baseUrl}/list`,{headers});
  }
  // tslint:disable-next-line:ban-types
  updateUser( user: User, id:number): Observable<Object> {
    const headers = new HttpHeaders({Authorization: 'Basic ' + localStorage.getItem('token')});
    return this.http.put(`${this.baseUrl}/updateUser/${id}`, user,{headers});
  }
  deleteUser(id: number): Observable<any> {
    const headers = new HttpHeaders({Authorization: 'Basic ' + localStorage.getItem('token')});
    return this.http.delete(`${this.baseUrl}/${id}`, { headers});
  }
  // @ts-ignore
  getRoleList(): Observable<any>{
    const headers = new HttpHeaders({Authorization: 'Basic ' + localStorage.getItem('token')});
    return this.http.get(`${this.baseUrl}/role/list`,{headers});
  }
}

, а вот мой component.ts для обновления входа пользователя в систему

import { Component, OnInit } from '@angular/core';
import {UserService} from '../../services/user.service';
import {User} from '../../models/user';
import {LoginService} from '../../services/login.service';
import {Role} from '../../models/role';
import {ActivatedRoute, Router} from '@angular/router';

@Component({
  selector: 'app-user-region',
  templateUrl: './user-region.component.html',
  styleUrls: ['./user-region.component.scss']
})
export class UserRegionComponent implements OnInit {
  user : User ;
  role : Role;
  constructor(private userService : UserService, private loginService : LoginService,
              private route: ActivatedRoute,private router: Router) { }
  updateUser(){
    this.userService.updateUser(this.user,this.user.role.role_id).subscribe(
      res => {
        console.log('updated');
      },
      err => {
        console.log(err);
      }
    );
  }
  goNext(){
    this.router.navigate(['/user/pinCode'])
  }
  ngOnInit(): void {
    this.loginService.getCurrentUser().subscribe(
      res =>{
        this.user = res
        console.log(this.user)},
      err => {
        console.log(err);
      }
    );
  }

}

Как Вы можете видеть в ошибке, что что-то не так в моем заявлении властей. Я думаю, что пробовал пользовательский конструктор пользовательского десериализатора, ничего не получилось. Любая помощь приветствуется.

...