如何在Spring Security中从发布方法获取用户名?

时间:2019-03-03 12:03:22

标签: spring-boot spring-security

我正在应用中使用spring-bootspring-security。我的目标是从post方法中获取当前注册用户的用户名。 Get方法运行良好,但post方法无效。为什么?我该如何解决这个问题?

测试控制器

@GetMapping("/test")
public String test(Authentication authentication) {
    System.out.println(authentication.getName()); // <--------- It's working
    return "testfile";
}

@PostMapping("/test")
public String testPost(Authentication authentication) {
    System.out.println(authentication.getName()); // <--------- NOLL ERROR!
    return "testfile";
}

错误

java.lang.NullPointerException: null

用户

@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    private long id;
    @Column(name="mail")
    private String mail;
    @Column(name="password")
    private String password;
}

UserDAO

@Repository
public class UserDAO {
    @Autowired
    private EntityManager entityManager;
    public List<User> findAll() {
        return entityManager.unwrap(Session.class).createQuery("from User", User.class).getResultList();
    }
    public User findByMail(String mail){
        Session currentSession = entityManager.unwrap(Session.class);
        Query theQuery = currentSession.createQuery("from User where mail=:mail", User.class);
        theQuery.setParameter("mail", mail);
        List<User> users = theQuery.getResultList();
        if(users.isEmpty()){
            return new User();
        }
        return users.get(0);
    }
    public void saveOrUpdate(User user) {
        Session currentSession = entityManager.unwrap(Session.class);
        currentSession.saveOrUpdate(user);
    }
}

UserService

public interface UserService extends UserDetailsService{
    public List<User> findAll();
    public User findByMail(String mail);
    public void saveOrUpdate(User user);
}

UserServiceImpl

@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserDAO userDAO;
    @Autowired
    private UserRoleDAO userRoleDAO;
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
    @Override
    @Transactional
    public List<User> findAll() {
        return userDAO.findAll();
    }
    @Override
    @Transactional
    public User findByMail(String mail){
       return userDAO.findByMail(mail);
    }
    @Override
    @Transactional
    public void saveOrUpdate(User user) {
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userDAO.saveOrUpdate(user);
    }
    @Override
    @Transactional
    public UserDetails loadUserByUsername(String mail) throws UsernameNotFoundException {
        User user = userDAO.findByMail(mail);
        List<UserRole> userRole = userRoleDAO.findByUserId(user.getId());
        if (user == null) {
            throw new UsernameNotFoundException("Invalid username or password.");
        }
        return new org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(), mapRolesToAuthorities(userRole));
    }
    private Collection<? extends GrantedAuthority> mapRolesToAuthorities(Collection<UserRole> roles) {
        return roles.stream().map(role -> new SimpleGrantedAuthority(role.getRole())).collect(Collectors.toList());
    }
}

SecurityConfig

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private Environment env;

@Autowired
private DataSource dataSource;

@Autowired
private UserService userService;

RedirectAuthenticationSuccessHandler redirectAuthenticationSuccessHandler = new RedirectAuthenticationSuccessHandler();

RedirectAuthenticationFailureHandler redirectAuthenticationFailureHandler = new RedirectAuthenticationFailureHandler();

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.jdbcAuthentication().dataSource(dataSource)
            .usersByUsernameQuery(env.getProperty("my.usersbyusernamequery"))
            .authoritiesByUsernameQuery(env.getProperty("my.authoritiesbyusernamequery"));
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
    http.authorizeRequests()
            .antMatchers("/anypage1/**").hasRole("MANAGER")
            .antMatchers("/anypage2/**").hasRole("ADMIN")
            .antMatchers("/test").hasRole("ADMIN")
            .authenticated()
            .antMatchers("/**").permitAll()
            .and()
            .formLogin().loginPage("/login").failureHandler(redirectAuthenticationFailureHandler)
            .loginProcessingUrl("/login-control").successHandler(redirectAuthenticationSuccessHandler).permitAll()
            .and()
            .logout().logoutUrl("/logout").permitAll().and().exceptionHandling().accessDeniedPage("/access-denied");
}

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers(HttpMethod.POST, "/anypage3").antMatchers(HttpMethod.POST, "/anypage4")
                  .antMatchers(HttpMethod.POST, "/test");
}

@Bean
public BCryptPasswordEncoder passwordEncoder()
{
    return new BCryptPasswordEncoder();
}

@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
    auth.setUserDetailsService(userService);
    auth.setPasswordEncoder(passwordEncoder());
    return auth;
}

}

2 个答案:

答案 0 :(得分:0)

您可以从SecurityContextHolder获取用户名

  

用户用户=   (User)SecurityContextHolder.getContext()。getAuthentication()。getPrincipal();   字符串名称= user.getUsername(); //获取当前登录的用户名

在loadUserByUsername方法中,您可以在SecurityContextHolder上手动设置身份验证令牌,也可以在控制器中使用相同的令牌

UsernamePasswordWithAttributesAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( loadUserByUsername(username), password, authorities );
    SecurityContextHolder.getContext().setAuthentication(authenticationToken);

答案 1 :(得分:0)

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers(HttpMethod.POST, "/anypage3").antMatchers(HttpMethod.POST, "/anypage4")
                  .antMatchers(HttpMethod.POST, "/test");
}

您在发布方法中忽略了/test,因此它不会被spring安全过滤器过滤,请尝试将其删除。