如何在 Spring Boot+JPA 中获取当前用户的对象

How to get an object of current user in Spring Boot+JPA

我需要创建购物车。我有一个模型 CartItem:

@Entity
@Table(name = "cart_items")
public class CartItem {
 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private int id;

 @ManyToOne
 @JoinColumn(name = "tour_id")
 private Tour tour;

 @ManyToOne
 @JoinColumn(name = "user_id")
 private User user;

 @Column(name = "order_date")
 private Date date=new Date();
 //getters and setters
}

模范用户:

package com.zaitsava.springboot_touristsite.entity;

import javax.persistence.*;
import java.util.Set;


@Entity
@Table(name = "user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @Column(name = "firstname")
    private String firstname;

    @Column(name = "lastname")
    private String lastname;

    @Column(name = "patronymic")
    private String patronymic;

    @Column(name = "email")
    private String email;

    @Column(name = "phone")
    private String phone;

    @Column(name = "password")
    private String password;

    @Column(name = "active")
    private int active;

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name="user_role", joinColumns=@JoinColumn(name="user_id"),
            inverseJoinColumns=@JoinColumn(name="role_id"))
    private Set<Role> roles;
    //gettes and setters
}

存储库:

public interface CartItemRepository extends JpaRepository<CartItem,Integer> {
    public List<CartItem> findByUser(User user);
}

@Service
public class ShoppingCartService {
    @Autowired
    private CartItemRepository cartItemRepository;

    public List<CartItem> cartItemList(User user){
        return cartItemRepository.findByUser(user);
    };}

现在我正在尝试获取用户并将其传递给视图:

 @GetMapping("/cart")
    public String showCart(Model model,@AuthenticationPrincipal User user){
        //User user = (User) auth.getPrincipal();  try 2
        //User user=(User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); try 3
        if(user==null) System.out.println("User is null");

        List<CartItem> cartItemList=cartService.cartItemList(user);
        model.addAttribute("cartItems",cartItemList);
        return "user/cart";
    }

在第一种情况下,我得到空值,在情况 2 和 3 中:

java.lang.ClassCastException: class org.springframework.security.core.userdetails.User cannot be cast to class com.zaitsava.springboot_touristsite.entity.User (org.springframework.security.core.userdetails.User and com.zaitsava.springboot_touristsite.entity.User are in unnamed module of loader 'app')-

我知道我应该注册 AuthenticationPrincipalArgumentResolver,但如何在 Spring 启动时注册?有必要吗?

更新 配置:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private DataSource dataSource;

    private final String USERS_QUERY = "select email, password, active from user where email=?";
    private final String ROLES_QUERY = "select u.email, r.role from user u inner join user_role ur on (u.id = ur.user_id) inner join role r on (ur.role_id=r.role_id) where u.email=?";

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication()
                .usersByUsernameQuery(USERS_QUERY)
                .authoritiesByUsernameQuery(ROLES_QUERY)
                .dataSource(dataSource)
                .passwordEncoder(bCryptPasswordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/user/cart").authenticated()
                .antMatchers("/login").permitAll()
                .antMatchers("/signup").permitAll()
                .antMatchers("favicon.ico").permitAll()
               /* .antMatchers("/admin/**").access("hasRole('ADMIN')")*/
                .antMatchers("/main/**").hasAuthority("ADMIN").anyRequest()
                .authenticated().and().csrf().disable()
                .formLogin().loginPage("/login").permitAll().failureUrl("/login?error=true")
                .defaultSuccessUrl("/")
                .usernameParameter("email")
                .passwordParameter("password")
                .and().logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/")
                .and().rememberMe()
                .tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(60 * 60)
                .and().exceptionHandling().accessDeniedPage("/access_denied");

    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers("/images/**")
                .antMatchers("/fonts/**");
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
        db.setDataSource(dataSource);

        return db;
    }
}

用户控制器:

package com.zaitsava.springboot_touristsite.controller;


import javax.validation.Valid;

import com.zaitsava.springboot_touristsite.entity.User;
import com.zaitsava.springboot_touristsite.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/signup")
    public ModelAndView signup() {
        ModelAndView model = new ModelAndView();
        User user = new User();
        model.addObject("user", user);
        model.setViewName("user/signup");
        return model;
    }

    @PostMapping("/signup")
    public ModelAndView createUser(@Valid User user, BindingResult bindingResult) {
        ModelAndView model = new ModelAndView();
        User userExists = userService.findUserByEmail(user.getEmail());

        if(userExists != null) {
            bindingResult.rejectValue("email", "error.user", "User with this email exists");
        }
        if(bindingResult.hasErrors()) {
            model.setViewName("user/signup");
        } else {
            userService.saveUser(user);
            model.addObject("msg", "User succesful register!");
            model.addObject("user", new User());
            model.setViewName("redirect:home/main");
        }

        return model;
    }



    @GetMapping("/home/main")
    public ModelAndView home() {
        ModelAndView model = new ModelAndView();
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User user = userService.findUserByEmail(auth.getName());

        model.addObject("userName", "Hello,"+user.getFirstname() + " " + user.getLastname()+" "+user.getPatronymic());
        model.setViewName("redirect:/");
        return model;
    }

    @GetMapping("/access_denied")
    public ModelAndView accessDenied() {
        ModelAndView model = new ModelAndView();
        model.setViewName("errors/access_denied");
        return model;
    }
}

我看到了我是如何制作控制器 User(method home()) 并为 ShoppingCartController 中的方法 showCart() 重新制作的

@GetMapping("/cart")
public String showCart(Model model){
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    User user = userService.findUserByEmail(auth.getName());
    if(user==null) System.out.println("User is null");
    List<CartItem> cartItemList=cartService.cartItemList(user);
    model.addAttribute("cartItems",cartItemList);
    return "user/cart";
}

现在 /cart link 显示当前用户的产品 link (对不起我的英语)