A,

When the front and back ends are separated, how to ensure the security of data interaction?

Someone: Token

Mobile terminal, applets, H5 and other clients also transmit data through JSON, which also involves identity verification

Second, the problem of

What is the best way to achieve Token?

Over one hundred projects (.(▼ and ▼). I’ve seen quite a few projects implemented this way

  • Token? We don’t need
  • Token write dead, background to provide the client (there are indeed many)
  • Token dynamic, the background through some algorithms to generate tokens, provided to the client (this way is not impossible, just not perfect)
  • The entire JSON data is encrypted and transmitted, and the key is provided in the background (em….) Don’t evaluation)
  • , etc.

Iii. Solutions

Today we are going to explain how to use JWT to solve the Token problem

# JWT

JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for transferring information between network applications. It is used as a JSON object for securely transferring information between different systems. The main usage scenario is generally used to pass authenticated user identity information between the identity provider and the service provider.

JWT consists of three parts, as follows:

  • Header contains two parts: the token type and the adopted signature algorithm
  • Payload is user-defined content carried by tokens. Data is base64. It is unencrypted and hackable. The more content, the longer the token
  • Signature The server calculates the Header and Payload as a string and obtains a Signature value based on the Signature algorithm. The server checks whether the Token is valid
# Explain Spring Security (bonus)

JWT can solve the problem of Token, and Spring Security can solve the problem of user permissions module (really powerful). Besides Spring Security, Apache Shiro can also solve the problem of user permissions, but not as powerful as Security. I will write a follow-up article detailing the comparison.

4. Implementation method

The introduction of JWT and Spring Security dependent jars in POM.xml

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId> IO. Jsonwebtoken </groupId> <artifactId> JJWT </artifactId> <version>0.9.1</version> </dependency>Copy the code

JWT utility class, generate Token, verify Token, refresh Token, etc

@Component
public class JwtTokenUtil {

    private static final String CLAIM_KEY_USERNAME = "sub";
    private static final String CLAIM_KEY_CREATED = "created"; Public String generateToken(UserDetails UserDetails) {... } // refreshToken public String refreshToken(String token) {... } public Boolean validateToken(String token) {... }}Copy the code

Token filter, which processes the tokens of interfaces

@Component
public class JwtTokenFilter extends OncePerRequestFilter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal (HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String authHeader = request.getHeader(Constant.HEADER_STRING );
        if(authHeader ! = null && authHeader.startsWith(Constant.TOKEN_PREFIX )) { final String authToken = authHeader.substring(Constant.TOKEN_PREFIX.length() ); String username = jwtTokenUtil.getUsernameFromToken(authToken);if(username ! = null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);if(jwtTokenUtil.validateToken(authToken, userDetails)) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails( request)); SecurityContextHolder.getContext().setAuthentication(authentication); } } } chain.doFilter(request, response); }}Copy the code

Core configuration for Spring Security

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userService;

    @Bean
    public JwtTokenFilter authenticationTokenFilterBean() throws Exception {
        return new JwtTokenFilter();
    }

    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        String[] urls = new String[]{"/user/login"."/user/register"}; httpSecurity.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() .authorizerequests () // Allows registration and login interfaces to be accessed without tokens.antmatchers (urls).permitall ().anyrequest ().authenticated(); httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); httpSecurity.headers().cacheControl(); }}Copy the code

Add @preauthorize to an interface to limit access limits

RestController Public Class RoleController {/** * Tests common permissions ** @return
     */
    @PreAuthorize("hasAuthority('ROLE_NORMAL')")
    @GetMapping(value="/normal/test")
    public String test1() {
        return "Normal Role Access"; } /** * Test administrator permissions ** @return
     */
    @PreAuthorize("hasAuthority('ROLE_ADMIN')")
    @GetMapping(value = "/admin/test")
    public String test2() {
        return "Administrator Access"; }}Copy the code

You need to add a role to the user to access the user, as shown in the following figure

How to verify the Token

Note: JWT is not encrypted by default and anyone can read it. You can copy a string of tokens to JWT for online decryption

eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJPd2F0ZXIiLCJjcmVhdGVkIjoxNTYzMzc2ODE2NTIzLCJleHAiOjE1NjMzODQwMTZ9.SuL4dRoweriLOnZzohcEzU wXf7kVSx9KnTIGtB7ffuBtlUUFS1T8il7_fxv3Gn1LkX5DGOawqNhG4ZWYxALDigCopy the code

As can be seen from the above, the information stored by token can be resolved, so do not store sensitive information here

So the token can’t be tampered with? No, because among the three parts of the token (Header, Payload, and Signature), Signature can prevent tampering. Only the server knows this key

Six, test effect

  • The token is returned after successful login

  • If the token is not carried, the access is denied

  • Correct access mode

The source code in this