User authentication with jwt under front-end and back-end separation

Keywords: Java axios Vue SpringBoot JSON

0 User Information Authentication with Front-end and Back-end Separation

The front end uses Vue+axios and the back end uses SpringBoot+SpringSecurity.

To solve the stateless problem of http, I use jwt(json web token) to save user information, bring it with the front end each time a request is made, and give it to the back end for user authentication.The problem to be solved at this time is how the back end returns the generated JWT to the front end, and how the front end carries the JWT with each request after it gets the jwt.

1 After the backend verifies that the user is successful, write the generated token in the response header

response.addHeader("Authorization", "Bearer " + jwt);

jwt is the token generated by itself and is of type String.

<!-- jwt rely on -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>
// Complete Code

/**
 * validate logon
 * Generate token and place in response header when login is successful
 */
public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    public JwtLoginFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    private static final Logger logger
            = LoggerFactory.getLogger(JwtLoginFilter.class);

    // attemptAuthentication() overridden has been omitted
    
    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response,
                                            FilterChain chain,
                                            Authentication authResult)
            throws IOException, ServletException {
        // Get User Roles
        Collection<? extends GrantedAuthority> authorities = authResult.getAuthorities();
        // My database has designed a user with only one role
        Iterator<? extends GrantedAuthority> iterator = authorities.iterator();
        String role = "";
        if (iterator.hasNext()) {
            role = iterator.next().getAuthority();
        }

        // Generate token
        String jwt = Jwts.builder()
                //Configuring user roles
                .claim("authorities", role)
                .setSubject(authResult.getName())
                //Expiration time, one hour
                .setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 1000))
                .signWith(SignatureAlgorithm.HS512, "secret key")
                .compact();

        //Write token in the response header
        response.addHeader("Authorization", "Bearer " + jwt);
        // Customize methods, set status codes for responses, etc.
        ResponseDataUtil.setDataInResponse(response,
                null,
                HttpStatusEnum.SUCCESSFUL,
                true);
    }
}

2 Backend opens the configuration so that the front end can get token in the response header

/**
 * Configure cors to address cross-domain resource issues for front-end access to back-end
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                //Front End Address Set
                .allowedOrigins("http://localhost:10011")
                .allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS", "HEAD")
                .allowedHeaders("*")
                //Expose the token saved in the request header to the front end for retrieval
                .exposedHeaders("Authorization");
    }
}

The important point is that exposedHeaders() is called, otherwise the front end cannot get the value of Authorization as the middle key in the response header.

The Authorization holding token has now been added to the response header of the login request.

3 Front end gets token in response header in callback function of login method

login() {
      // Validate the validity of form data
      this.$refs.loginFormRef.validate(async valid => {
        if (!valid) return
        // Form data is valid, send request
        const data = await this.$request.postWithBody('login', this.loginForm)
        if (data.successful) {
          // Save token locally
          window.sessionStorage.setItem('jwt', data.token)
          this.$router.push('/home')
        }
      })
    }

this.$request.postWithBody('login', this.loginForm) is my own encapsulated axios method for sending post requests.Of course, the original axios post method can be used.

window.sessionStorage.setItem('jwt', data.token) saves the token returned from the background locally.JWT is the key of this key-value pair and can be named according to your own custom.

4 Front-end axios configures request interceptors, adding token to each request

// request interceptor
axios.interceptors.request.use(request => {
  // Show progress bar
  Nprogress.start()
  request.headers.Authorization = window.sessionStorage.getItem('jwt')
  return request
})

This step intercepts each request sent by the front end and adds the jwt obtained in step 3 to the request header.

5 Effect

At this time, the request sent by the front-end has joined jwt in the request header. When the back-end receives the request, the token in the request header is taken out for parsing and user authentication is completed.

This article is distributed by blogs and other operating tool platforms OpenWrite Release

Posted by mega77 on Wed, 22 Apr 2020 18:43:37 -0700