你能帮我处理这种情况吗?我正在开发一个移动应用程序,在Spring Boot服务器端没有维护会话。因此,我正在使用JWT,客户端每次请求时都会发送令牌。
客户端应用程序将数据与令牌一起(按请求逐页)发送到服务器。服务器需要临时存储这些数据并等待响应数据到达。它必须全部或不全部存储在数据库中。
通常,对于传统的Web应用程序,这是通过会话实现的。我尝试使用会话,但它无法保持维护。但是,当请求来自Postman时,会话是维护的。客户端应用程序运行在端口8000上,而服务器运行在SSL端口8443上。有一件事很明确,服务器认为来自同一客户端的每个请求都是匿名的,尽管每个请求都接收到了令牌。
SecurityConfigurer.java
@EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter{
@Autowired
private MyUserDetailsService userDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.cors().and()
.authorizeRequests().antMatchers("/authenticate").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
// TODO Auto-generated method stub
return super.authenticationManagerBean();
}
}
JwtRequestFilter.java
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private MyUserDetailsService userDetailsService;
@Autowired
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtUtil.extractUsername(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods",
"POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age",
"3600");
filterChain.doFilter(request, response);
}
}
QuizController.java
@CrossOrigin("*")
@RestController
public class QuizController {
@Autowired
private QuizRepository service;
@Autowired
private QuizSummaryRespository summaryService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private MyUserDetailsService userDetailsService;
@Autowired
private JwtUtil jwtTokenUtil;
@SuppressWarnings("unchecked")
@ResponseBody
@PostMapping("/quiz")
public ResponseEntity<?> saveQuiz(Quiz quiz, @RequestParam String status, @RequestParam long time,
HttpServletRequest request, HttpServletResponse response, @RequestHeader Map<String, String> headers) {
Map<String, String> map = new HashMap<>();
List<Quiz> myQuizzes = (List<Quiz>) request.getSession().getAttribute("code"); //This line always return null list
if (quiz.getCode().equals("")) {
quiz.setCode(Utility.generateCode());
myQuizzes = new ArrayList<>();
}
myQuizzes.add(quiz);
request.getSession().setAttribute("code", myQuizzes);
map.put("code", quiz.getCode());
return ResponseEntity.ok(map);
}
}