मैं वसंत सुरक्षा में टोकन को कैसे ताज़ा कर सकता हूं

Aug 15 2020

यह रेखा:

Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();

मेरे jwt टोकन की समय सीमा समाप्त होने पर इस तरह एक त्रुटि:

JWT 2020-05-13T07: 50: 39Z पर समाप्त हो गया। वर्तमान समय: 2020-05-16T21: 29: 41Z

विशेष रूप से, यह वह फ़ंक्शन है जो "एक्सपायर्डजवाइटएक्स अपवाद" को फेंकता है:

इन अपवादों को संभालने के बारे में मैं क्या करूँ? क्या मुझे उन्हें पकड़ना चाहिए और क्लाइंट को एक त्रुटि संदेश भेजना चाहिए और उन्हें फिर से लॉगिन करने के लिए मजबूर करना चाहिए?

मैं एक ताज़ा टोकन सुविधा कैसे लागू कर सकता हूं? मैं बैकएंड में वसंत और mysql का उपयोग कर रहा हूं और सामने के अंत में vuejs।

मैं इस तरह से प्रारंभिक टोकन उत्पन्न करता हूं:

   @Override
        public JSONObject login(AuthenticationRequest authreq) {
            JSONObject json = new JSONObject();
    
            try {
                Authentication authentication = authenticationManager.authenticate(
                        new UsernamePasswordAuthenticationToken(authreq.getUsername(), authreq.getPassword()));
    
                UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
                List<String> roles = userDetails.getAuthorities().stream().map(item -> item.getAuthority())
                        .collect(Collectors.toList());
    
                if (userDetails != null) {
    
                    final String jwt = jwtTokenUtil.generateToken(userDetails);
    
    
                    JwtResponse jwtres = new JwtResponse(jwt, userDetails.getId(), userDetails.getUsername(),
                            userDetails.getEmail(), roles, jwtTokenUtil.extractExpiration(jwt).toString());
    
                    return json.put("jwtresponse", jwtres);
                }
            } catch (BadCredentialsException ex) {
                json.put("status", "badcredentials");
            } catch (LockedException ex) {
                json.put("status", "LockedException");
            } catch (DisabledException ex) {
                json.put("status", "DisabledException");
            }
    
            return json;
        }

और फिर JwtUtil क्लास में:

   public String generateToken(UserDetails userDetails) {
            Map<String, Object> claims = new HashMap<>();
            return createToken(claims, userDetails.getUsername());
        }
    
   private String createToken(Map<String, Object> claims, String subject) {
            return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
                    .setExpiration(new Date(System.currentTimeMillis() + EXPIRESIN))
                    .signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
        }

अधिक जानकारी के लिए, यहाँ मेरा doFilterInternal फ़ंक्शन है जो हर अनुरोध को फ़िल्टर करता है:

   @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException, ExpiredJwtException, MalformedJwtException {

        try {

            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 = userService.loadUserByUsername(username);

                boolean correct = jwtUtil.validateToken(jwt, userDetails);

                if (correct) {
                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                            userDetails, null, userDetails.getAuthorities());

                    usernamePasswordAuthenticationToken
                            .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);

                }
            }

            chain.doFilter(request, response);
        } catch (ExpiredJwtException ex) {
            resolver.resolveException(request, response, null, ex);
        }
    } 

जवाब

3 doctore Aug 16 2020 at 17:38

ऐसी स्थितियों से निपटने के लिए 2 मुख्य दृष्टिकोण हैं:


पहुँच और ताज़ा टोकन प्रबंधित करें

इस मामले में, प्रवाह निम्नलिखित है:

  1. आवेदन (सहित usernameऔर password) में उपयोगकर्ता लॉगिन

  2. आपका बैकएंड आवेदन किसी भी आवश्यक क्रेडेंशियल जानकारी देता है और:

    2.1 एक्सेस किए गए JWT टोकन की समय सीमा समाप्त होने के साथ आमतौर पर "कम" (15, 30 मिनट, आदि)।

    2.2 JWT टोकन को एक्सेस किए गए समय से अधिक समय के साथ रिफ्रेश करें

  3. अब से, अपने दृश्यपटल आवेदन का उपयोग करेगा access tokenमें Authorizationहर अनुरोध के लिए शीर्ष लेख।

जब बैकएंड वापस आ जाता है 401, तो फ्रंटएंड एप्लिकेशन refresh tokenनए क्रेडेंशियल प्राप्त करने के लिए (एक विशिष्ट समापन बिंदु का उपयोग करके) उपयोग करने का प्रयास करेगा , उपयोगकर्ता को फिर से लॉगिन करने के लिए मजबूर किए बिना।

ताज़ा प्रवाह (यह केवल एक उदाहरण है, आमतौर पर केवल ताज़ा टोकन भेजा जाता है)

यदि कोई समस्या नहीं है, तो उपयोगकर्ता एप्लिकेशन का उपयोग करना जारी रखने में सक्षम होगा। यदि बैकएंड एक नया रिटर्न देता है तो 401= लॉगिन पेज पर रीडायरेक्ट करना चाहिए।


केवल एक Jwt टोकन प्रबंधित करें

इस मामले में, प्रवाह पिछले एक के समान है और आप इस तरह की स्थितियों से निपटने के लिए अपना स्वयं का समापन बिंदु बना सकते हैं: /auth/token/extend(उदाहरण के लिए), अनुरोध के पैरामीटर के रूप में समाप्त जेवीटी सहित।

अब यह आप पर निर्भर है:

  • इसका विस्तार करने के लिए Jwt टोकन का कितना समय "वैध" होगा?

नए समापन बिंदु पर पिछले खंड में एक ताज़ा करने का समान व्यवहार होगा, मेरा मतलब है, एक नया Jwt टोकन लौटाएगा या 401, दृश्यपटल के दृष्टिकोण से प्रवाह समान होगा।


एक महत्वपूर्ण बात , जिस दृष्टिकोण का आप अनुसरण करना चाहते हैं, उसके लिए "नए समापन बिंदु" को आवश्यक स्प्रिंग प्रमाणित समापन बिंदुओं से बाहर रखा जाना चाहिए, क्योंकि आप स्वयं सुरक्षा का प्रबंधन करेंगे:

public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
  ..

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.
      ..
      .authorizeRequests()
      // List of services do not require authentication
      .antMatchers(Rest Operator, "MyEndpointToRefreshOrExtendToken").permitAll()
      // Any other request must be authenticated
      .anyRequest().authenticated()
      ..
   }
}
2 QuocTruong Aug 16 2020 at 18:18

नीचे दिए गए ताज़ा टोकन प्राप्त करने के लिए आप एपीआई को कॉल कर सकते हैं

POST https://yourdomain.com/oauth/token 

Header
  "Authorization": "Bearer [base64encode(clientId:clientSecret)]" 

Parameters
  "grant_type": "refresh_token"
  "refresh_token": "[yourRefreshToken]"

कृपया ध्यान दें कि,

  • base64encode क्लाइंट प्राधिकरण को एन्क्रिप्ट करने की विधि है। आप ऑनलाइन उपयोग कर सकते हैंhttps://www.base64encode.org/
  • refresh_token की स्ट्रिंग मान है grant_type
  • yourRefreshToken है ताज़ा टोकन के साथ प्राप्त जेडब्ल्यूटी पहुँच टोकन

परिणाम के रूप में देखा जा सकता है

{
    "token_type":"bearer",
    "access_token":"eyJ0eXAiOiJK.iLCJpYXQiO.Dww7TC9xu_2s",
    "expires_in":20,
    "refresh_token":"7fd15938c823cf58e78019bea2af142f9449696a"
}

सौभाग्य।