'How to get an object of current user in Spring Boot+JPA
I need to create shopping cart. I have a model 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
}
Model User:
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
}
Repository:
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);
};}
Now I'm trying to get the user and pass it to view:
@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";
}
In the first case I get null value, in case 2 and 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')-
I know that I should register AuthenticationPrincipalArgumentResolver, but how do it in Spring Boot? And is it need?
Update configuration:
@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;
}
}
User Controller:
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;
}
}
Solution 1:[1]
I saw how I made controller User(method home()) and remade for a method showCart() in ShoppingCartController
@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";
}
Now the /cart link displays the product link for the current user (Sorry for my English)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Yan Zaitsau |