Управление сеансами Spring Boot с помощью JWT - PullRequest
0 голосов
/ 13 апреля 2020

Можете ли вы кто-нибудь помочь мне в сценарии. Я занимаюсь разработкой мобильного приложения, в котором сеанс не поддерживается на стороне сервера весенней загрузки. Поэтому я использую JWT, который клиент отправляет с каждым запросом.

Клиентское приложение отправляет данные вместе с токеном постранично (запрос за запросом) на сервер. Сервер должен хранить эти данные временно и ожидает получения полных данных. Он должен хранить все данные или ничего в базе данных.

Обычно, с традиционными веб-приложениями, это было возможно через сеанс. Я пытался с сеансом, но он не поддерживается. Тем не менее, сеанс сохраняется, когда запрос приходит от почтальона. Клиентское приложение работает на порте 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);
    }
}

1 Ответ

0 голосов
/ 13 апреля 2020

Хорошо, есть несколько способов, с помощью которых я могу решить эту проблему.

Первый подход

Во внешнем интерфейсе хранить все предыдущие ответы в sessionStorage или localStorage и отправить все сразу, когда закончите.

Второй подход

В бэкэнде во время первого запроса сохраните ответ с уникальным идентификатором и отправьте уникальный идентификатор клиенту. В каждом последующем запросе клиент должен будет отправить этот уникальный идентификатор вместе с заказом и ответом. После этого получите все ответы и объедините их по порядку. Здесь вы можете использовать любой тип хранилища: базу данных, кеш или обычный массив. Все, что соответствует вашим потребностям.

...