如何在 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
(对不起我的英语)
我需要创建购物车。我有一个模型 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 (对不起我的英语)