1. Introduction

Welcome to the Spring Security Hands-on articles series, where we implemented the JWT tool. In this article, we will explore how to combine JWT with Spring Security to return the JWT Token after successful authentication instead of jumping to the specified page. The DEMO is available at the end of this article

2. Process

JWT is suitable for front and rear end separation. After a successful login, the JWT Token pair (JwtTokenPair in DEMO) is directly returned. After a login failure, information about authentication failure is returned.

3. Implement the login success/failure return logic

If you’ve seen Spring Security in action: Playing with custom logins it will be very easy to understand what follows.

3.1 return to JWT AuthenticationSuccessHandler Token

AuthenticationSuccessHandler for processing after the success of the login logic, we write the implementation and inject the Spring IoC container:

** @param jwtTokenGenerator The JWT TokenGenerator * @return the authentication success handler */ @Bean public AuthenticationSuccessHandler authenticationSuccessHandler(JwtTokenGenerator jwtTokenGenerator) {  return (request, response, authentication) -> { if (response.isCommitted()) { log.debug("Response has already been committed"); return; } Map<String, Object> map = new HashMap<>(5); map.put("time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); map.put("flag", "success_login"); User principal = (User) authentication.getPrincipal(); String username = principal.getUsername(); Collection<GrantedAuthority> authorities = principal.getAuthorities(); Set<String> roles = new HashSet<>(); if (CollectionUtil.isNotEmpty(authorities)) { for (GrantedAuthority authority : authorities) { String roleName = authority.getAuthority(); roles.add(roleName); } } JwtTokenPair jwtTokenPair = jwtTokenGenerator.jwtTokenPair(username, roles, null); map.put("access_token", jwtTokenPair.getAccessToken()); map.put("refresh_token", jwtTokenPair.getRefreshToken()); ResponseUtil. ResponseJsonWriter (response, RestBody. OkData (map, "login succeeds")); }; }Copy the code

3.2 AuthenticationFailureHandler returned authentication failure information

AuthenticationFailureHandler processing logic of authentication failed, the front return to processing logic jump according to this, we also implement it and into the Spring IoC container:

** @return the authentication failure handler */ @bean public AuthenticationFailureHandler authenticationFailureHandler() { return (request, response, exception) -> { if (response.isCommitted()) { log.debug("Response has already been committed"); return; } Map<String, Object> map = new HashMap<>(2); map.put("time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); map.put("flag", "failure_login"); ResponseUtil. ResponseJsonWriter (response, RestBody. Build (HttpStatus. UNAUTHORIZED. Value (), map, "authentication failed", "9999")); }; }Copy the code

4. Configuration

Write the two Handler beans to the login configuration as shown in the following snippet (see the DEMO at the end of this article) :

httpSecurity.formLogin().loginProcessingUrl(LOGIN_PROCESSING_URL).successHandler(authenticationSuccessHandler).failureHa ndler(authenticationFailureHandler)Copy the code

5. Verify

We still run it through the Spring Security hands-on: Playing with custom logins section 6.4 tests in this article. The results are as follows:

5.1 Login Result

{ "httpStatus": 200, "data": { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbGwiLCJhdWQiOiJGZWxvcmRjbiIsInJvbGVzIjoiW10iLCJpc3MiOiJmZWxvcmQuY24iLC JleHAiOiIyMDE5LTExLTI3IDExOjMxOjMyIiwiaWF0IjoiMjAxOS0xMC0yOCAxMTozMTozMiIsImp0aSI6IjdmYTBlOWFiYjk5OTRjZGRhNGM5NjI4YzExNG M3YTk4In0.PvVsc8w10_0C5UIifJS1S5dEia5PQoVc_6wMfLAZOf574kt-VopHBVEp2zkjC1CNN3ltchy5rx6samaBDQvqWgoeFLXbRgNOa9Qhdf0wMLf-pU qoKRHuhBZV9HsvXSyQCFjZWlIguv4FSPZhbEff6D_8QUXmdWjlF_XEG2BPMr4", "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbGwiLCJhdWQiOiJGZWxvcmRjbiIsInJvbGVzIjoiW10iLCJpc3MiOiJmZWxvcmQuY24iLC JleHAiOiIyMDIwLTAxLTI2IDExOjMxOjMyIiwiaWF0IjoiMjAxOS0xMC0yOCAxMTozMTozMiIsImp0aSI6IjdmYTBlOWFiYjk5OTRjZGRhNGM5NjI4YzExNG M3YTk4In0.Caj4AAothdUwZAFl8IjcAZmmXHgTt76z8trVG1sf_WHZucFVcHR8FWjShhITpArsQpmokP6GBTMsCvWDl08fUVZBpOWc1CdPUAIIEdArHCFzO6 4HXc_DLSyg9v0C-qYfxaTlf0npL5QxpBBr9sJcyzxZF3CnpfZpAxm8WZzXG6o", "time": "2019-10-28 11:32:11", "flag": "Success_login}" and "MSG", "login succeeds" and "identifier" : ""}Copy the code

We take the access_token and use the decoding function provided by the official website jwt. IO to decode as follows:

5.2 Result of Login Failure

{" httpStatus: "401," data ": {" time" : "the 2019-10-28 12:54:10", "flag" : "failure_login}", "MSG" : "authentication failed", "identifier" : "- 9999"}Copy the code

6. Summary

Today we have linked JWT with Spring Security to return a JWT Token after a successful login. This is just the beginning. Stay tuned for the next article, which will cover how clients use JWT tokens and how servers validate JWT tokens.

The DEMO of this article can be obtained by following the public account: Felordcn and replying to ss06.

Follow our public id: Felordcn for more information

Personal blog: https://felord.cn