Spring 安全,主体返回 null
Posted
技术标签:
【中文标题】Spring 安全,主体返回 null【英文标题】:Spring security , Principal returns null 【发布时间】:2021-06-06 12:26:42 【问题描述】:我正在尝试使用 postman 将对象发布到数据库,令牌生成 corectlly 但主体为空!?为什么 在控制器中我有以下代码。 和错误如图 主体 tostring 是: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);
【问题讨论】:
请编辑您的问题以添加您的UserDetailsService 实现的源代码。它可能没有从您的用户帐户数据库中读取电子邮件字段。 也许是 Spring Security - 不访问数据库如何允许所有 MySQL db url @ChinHuang 完成 你的 UserService 类没有实现 Spring Security 的UserDetailsService 接口。你有另一个实现 UserDetailsService 的类吗? @chinHuang 是的,我在上面添加了它 【参考方案1】:确保您的令牌具有sub
属性。使用此工具发布您的令牌的内容(减去任何安全属性)。
https://jwt.io/
【讨论】:
它给了我一个 Invalid Signature ,似乎是访问令牌中的错误! @AhmadAmer 很高兴你发现了这一点。您的身份提供者应该生成一个有效的令牌。也许您的 IDP 有错误? 主体中的错误,因为它返回一个空值,我检查了令牌并正确生成了它。如果我通过静态电子邮件传递 prncipal.getNAme() 一切正常以上是关于Spring 安全,主体返回 null的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot安全主体用户已更改为新登录的用户详细信息
Spring Security 在登录失败时返回 String 作为主体而不是 UserDetails?
Spring Security Oauth2:主体对象未返回扩展的用户详细信息