我正在开发一个启用了休息功能的Spring Boot应用程序。我有一些使用Spring Boot开发应用程序的经验。
但是奇怪的是,我注意到传递给sprint引导api的输入值始终被接收为null。
当我从邮递员调用该方法时,我看到该方法正在按要求被调用。但是,当我打印userdata输入参数时,我注意到所有属性的值都是null,但是变量userdata本身不是null。
@CrossOrigin(origins = "*",maxAge = 3600)
@RestController
@RequestMapping("api/user")
public class UserController {
@CrossOrigin
@RequestMapping(value = "/create",method = RequestMethod.POST)
public UserResponse createNewUser(@RequestBody User userdata) throws Exception {
logger.info("Inside createNewUser() API");
logger.info("username: " + userdata.getusername());
logger.info("Password: " + userdata.getPassword());
UserResponse userResponse = new UserResponse();
try {
User userRec = userService.save(userdata);
userResponse.setId(userRec.getId());
userResponse.setusername(userRec.getusername());
userResponse.setName(userRec.getName());
userResponse.setactive(userRec.getactive());
}
catch (Exception ex) {
ex.printStackTrace();
}
logger.info("Leaving createNewUser() API");
return userResponse;
}
}
User.java
@Entity
@Table(name="USER")
@Scope("session")
public class User implements Serializable,UserDetails {
private static final long serialVersionUID = 20191225001L;
@Id
@Column(name="USER_ID",length = 255)
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "seller_id_seq")
@GenericGenerator(
name = "seller_id_seq",strategy = "com.app.mycompany.ekart.ekartSellerServices.util.SellerIdGenerator",parameters = {
@Parameter(name = SellerIdGenerator.INCREMENT_PARAM,value = "1"),@Parameter(name = SellerIdGenerator.VALUE_PREFIX_PARAMETER,value = "CUST_"),@Parameter(name = SellerIdGenerator.NUMber_FORMAT_PARAMETER,value = "%05d") })
private String id;
@JsonProperty(value="username")
@Column(name="username",nullable = false,unique = true)
private String username;
@JsonProperty(access = access.WRITE_ONLY,value="password")
@Column(name="PASSWORD")
private String password;
/* removed the getter & setter for brevity */
}
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.6.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
CORSFilter.java
public class CORSFilter {
public void doFilter(ServletRequest req,ServletResponse res,FilterChain chain) throws IOException,ServletException {
System.out.println("Filtering on...........................................................");
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("access-control-allow-origin","*");
response.setHeader("access-Control-Allow-Credentials","true");
response.setHeader("access-Control-Allow-Methods","POST,GET,PUT,OPTIONS,DELETE");
response.setHeader("access-Control-Max-Age","3600");
response.setHeader("access-Control-Allow-Headers","X-Requested-With,Content-Type,Authorization,Origin,accept,access-Control-Request-Method,access-Control-Request-Headers");
response.setHeader("access-Control-Expose-Headers",expiresIn,access-Control-Request-Headers");
//chain.doFilter(req,res);
final HttpServletRequest request = (HttpServletRequest) req;
if (!request.getMethod().equals("OPTIONS")) {
chain.doFilter(req,res);
} else {
// do not continue with filter chain for options requests
System.out.println("Pre-fight");
response.setHeader("access-Control-Allowed-Methods",DELETE,");
response.setHeader("access-Control-Max-Age","3600");
response.setHeader("access-control-allow-origin","*");
response.setHeader("access-Control-Allow-Headers","Authorization,content-type,x-auth-token," +
"access-control-request-headers,access-control-request-method,accept,origin,authorization,x-requested-with");
response.setHeader("access-Control-Expose-Headers",x-requested-with,expiresIn");
response.setStatus(HttpServletResponse.SC_OK);
}
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
WebConfig.java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService userDetailsService;
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Override
@Bean
public Authenticationmanager authenticationmanagerBean() throws Exception {
return super.authenticationmanagerBean();
}
@Autowired
public void globalUserDetails(AuthenticationmanagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(encoder());
}
@Bean
public JwtAuthenticationFilter authenticationTokenFilterBean() throws Exception {
return new JwtAuthenticationFilter();
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET","PUT","POST","OPTIONS","DELETE")
.allowedHeaders("accept","access-Control-Request-Method","access-Control-Request-Headers","access-control-allow-origin","Content-Type","Authorization","access-Control-Allow-Headers","Origin","GET","DELETE")
.exposedHeaders("Authorization","expiresIn");
}
};
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/user/create").permitAll()
.antMatchers("/auth/login").permitAll()
.anyRequest().authenticated()
.and()
.logout().permitAll().logoutRequestMatcher(new AntPathRequestMatcher("/logout","POST"))
.and()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionmanagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(authenticationTokenFilterBean(),usernamePasswordauthenticationFilter.class);
}
@Bean
public BCryptPasswordEncoder encoder(){
return new BCryptPasswordEncoder();
}
}
JwtAuthenticationFilter.java
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest req,HttpServletResponse res,ServletException {
String header = req.getHeader(HEADER_STRING);
String username = null;
String authToken = null;
if (header != null && header.startsWith(TOKEN_PREFIX)) {
authToken = header.replace(TOKEN_PREFIX,"");
try {
username = jwtTokenUtil.getusernameFromToken(authToken);
} catch (IllegalArgumentException e) {
logger.error("an error occured during getting username from token",e);
} catch (ExpiredJwtException e) {
logger.warn("the token is expired and not valid anymore",e);
} catch(SignatureException e){
logger.error("Authentication Failed. username or Password not valid.");
}
} else {
logger.warn("couldn't find bearer string,will ignore the header");
}
if (username != null && SecurityContextHolder.getcontext().getauthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByusername(username);
if (jwtTokenUtil.validateToken(authToken,userDetails)) {
usernamePasswordauthenticationToken authentication = new usernamePasswordauthenticationToken(userDetails,null,Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN")));
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(req));
logger.info("authenticated user " + username + ",setting security context");
SecurityContextHolder.getcontext().setauthentication(authentication);
}
}
chain.doFilter(req,res);
}
}
POSTMAN输入
Header = Content-type:application/json
Body = {"username":"abc@innovate.com","password":"password","roles": [{"name":"USER"}]}