Spring security , Principal 返回 null

发布时间:2021-03-08 15:51

我正在尝试使用 postman 将对象发布到数据库,令牌正确生成,但主体为空!?为什么 在控制器中,我有以下代码。 和错误如图所示 主体字符串是: UsernamePasswordAuthenticationToken [Principal=com.accessjobs.pjp.domain.User@1a1e348b, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0 :1, SessionId=null], 授予权限=[]] :主体 getName 是:null


@RestController
@RequestMapping("/api/job")
@CrossOrigin //to hit the backend server when connect from the frontend server
public class JobController {

    Logger logger = LoggerFactory.getLogger(JobController.class);

    @Autowired
    private JobService jobService;
    @Autowired
    private MapValidationErrorsService mapValidationErrorsService;

    //@valid annotation to validate the object attributes and , i used the following code FieldErrors to display the list of errors from validation
    @PostMapping("")
    @CrossOrigin
    public ResponseEntity<?> add(@Valid @RequestBody Job job, BindingResult result, Principal principal) {

        ResponseEntity<?> errorMap = mapValidationErrorsService.MapValidationService(result);
        if (errorMap != null) return errorMap;

        logger.info("the principal tostring is : "+principal.toString());
        logger.info("the principal getName is : "+principal.getName());

        Job tempJob = jobService.add(job, principal.getName());
        return new ResponseEntity<Job>(tempJob, HttpStatus.CREATED);
    }

和如图所示的服务作业代码,总是给我一个空用户并捕获错误。 那是因为电子邮件为空。 有什么解决办法>?


import com.accessjobs.pjp.domain.Job;
import com.accessjobs.pjp.domain.User;
import com.accessjobs.pjp.exceptions.JobIdException;
import com.accessjobs.pjp.repositories.JobRepository;
import com.accessjobs.pjp.repositories.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Locale;

@Service
public class JobService {
    Logger logger = LoggerFactory.getLogger(JobService.class);

    @Autowired
    private JobRepository jobRepository;
    @Autowired
    private UserRepository userRepository;

    public Job add(Job job,String email){
        //logic , validation and handling
        try {
            logger.info("email .is"+email);
            User user = userRepository.findByEmail(email);
            logger.info("user is ::"+user.toString());
            job.setUser(user);
            logger.warn(user.getEmail());
            job.setUserRole(user.getRole());
            logger.info(user.getRole());
            //convert the identifier to upper case
            job.setJobIdentifier(job.getJobIdentifier().toUpperCase(Locale.ROOT));
            return jobRepository.save(job);
        }catch (Exception e){
            throw new JobIdException("Job Identifier '"+job.getJobIdentifier().toUpperCase(Locale.ROOT)+"' already exists");
        }
    }


package com.accessjobs.pjp.services;

import com.accessjobs.pjp.domain.User;
import com.accessjobs.pjp.exceptions.EmailAlreadyExistsException;
import com.accessjobs.pjp.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    @Autowired //define the bean in the main spring boot app
    private BCryptPasswordEncoder bCryptPasswordEncoder;//store non readable password in the database

    public User register(User newUser){
        try{
            newUser.setPassword(bCryptPasswordEncoder.encode(newUser.getPassword()));
            //user name has to be unique (exception)
            newUser.setEmail(newUser.getEmail());
            //make sure that pass and confpass are matches
            //we dont presist or show the confirm password
            newUser.setConfirmPassword("");
            return userRepository.save(newUser);

        }catch (Exception e){
            throw new EmailAlreadyExistsException("Email' "+newUser.getEmail()+"' is already exists");
        }

    }
}

可能是数据库错误,如何允许MySQL数据库的所有URL

这是实现用户详细信息服务的类

package com.accessjobs.pjp.services;


import com.accessjobs.pjp.domain.User;
import com.accessjobs.pjp.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        User user = userRepository.findByEmail(email);
        if(user==null) new UsernameNotFoundException("User not found");
        return user;
    }


    @Transactional
    public User loadUserById(Long id){
        User user = userRepository.getById(id);
        if(user==null) new UsernameNotFoundException("User not found");
        return user;

    }
}

这个类有什么错误吗? 尤其是在 MySQL 权限和 antMatchers 方面?

package com.accessjobs.pjp.security;

import com.accessjobs.pjp.services.CustomUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import static com.accessjobs.pjp.security.SecurityConstants.*;

//video rep branch 65


@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        securedEnabled = true,
        jsr250Enabled = true,
        prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationEntryPoint unauthorizedHandler;
    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() {
        return new JwtAuthenticationFilter();
    }

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(customUserDetailsService).passwordEncoder(bCryptPasswordEncoder);
    }

    @Override
    @Bean(BeanIds.AUTHENTICATION_MANAGER)
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                // .and().headers().frameOptions().sameOrigin() //To enable H2 Database
                .and()
                .authorizeRequests()
                .antMatchers(
                        "/",
                        "/favicon.ico",
                        "/**/*.png",
                        "/**/*.gif",
                        "/**/*.svg",
                        "/**/*.jpg",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js"
                ).permitAll()
                .antMatchers("/api/users/**").permitAll()
                .antMatchers(SIGN_UP_URLS).permitAll()
                .antMatchers("jdbc:mysql://localhost:3306/").permitAll()**//here ?**
                .antMatchers("/api/users/**").permitAll()
                .antMatchers("/api/users/**").permitAll()
                .anyRequest().authenticated();

        http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }
}
回答1

确保您的令牌具有 sub 属性。使用此工具发布您的令牌内容(减去任何安全属性)。

https://jwt.io/