Tech Info

  1. Main page
  2. Backend
  3. Main content

Use Cases of Spring Security

2023-10-02 417hotness 0likes 0comments

1. Background

When doing the general permission system, I used spring-security to control the permission system, and now I will summarize the most basic usage

2. Demo usage

2.1 Some basic concepts

Spring Security's security management has two important concepts, Authentication and Authorization

Spring Security login authentication mainly involves two important interfaces: UserDetailService and UserDetails. The UserDetailService interface mainly defines a method loadUserByUsername(String username) to complete the query of user information. username is the login name when logging in. When logging in and authenticating, you need to customize an implementation class to implement the UserDetailService interface and complete the database query. This interface returns UserDetail.

The loadUserByUsername user returns UserDetails. Our own User implements UserDetails

UserDetail is mainly used to encapsulate user information after successful authentication, that is, the user information returned by UserDetailService can use Spring's own User object, but it is best to implement the UserDetail interface and customize the user object

What is returned after successful authentication token

The token is a string generated by the server as a token for the client to request. After the first login, the server generates a token and returns this token to the client. In the future, the client only needs to bring this token to request data without having to bring the username and password again

Basic dependencies

<dependency>
    <groupId>org.springframework.boot</groupId>    
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2.2 Spring Security authentication steps

  1. Customize the UserDetails class: When the entity object fields do not meet the requirements, you need to customize UserDetails, generally you need to customize UserDetails

  2. Customize the UserDetailsService class, mainly used to query user information from the database.

    Implement the UserDetails interface in the User class

    Modify the original isAccountNonExpired, isAccountNonLocked, isCredentialsNonExpired and isEnabled properties to boolean type, and add authorities properties.

  3. Create a login authentication success handler, you need to return JSON data, menu permissions, etc. after successful authentication

    LoginSuccessHandler implements AuthenticationSuccessHandler

    Implement the onAuthenticationSuccess method

    Generate token, create login result object, get output stream, save generated token to redis

  4. Create a login authentication failure handler, authentication failure needs to return JSON data for the front end to judge.

    LoginFailureHandler implements AuthenticationFailureHandler, override onAuthenticationFailure() method

    String result = 
            JSON.toJSONString(Result.error().code(code).message(message));
    outputStream.write(result.getBytes(StandardCharsets.UTF_8));
    outputStream.flush();
    outputStream.close();
    
  5. Create a handler when an anonymous user accesses a resource without permission. JSON needs to be prompted when an anonymous user accesses.

    CustomerAccessDeniedHandler implements AccessDeniedHandler

  6. Create a handler when an authenticated user accesses a resource without permission. JSON needs to be prompted when there is no permission to access.

    AnonymousAuthenticationHandler implements AuthenticationEntryPoint

  7. Configure the Spring Security configuration class to hand over the custom handlers to Spring Security.

2.3 Custom UserDetails class

3. JWT principle and usage

A typical example of trading space for time design pattern

3.1 Advantages of JWT

  • Compact: Can be sent via URL, POST parameters or in HTTP header, because the data volume is small, the transmission speed is also very fast

  • Self-contained: The payload contains all the information the user needs, avoiding multiple database queries

  • Because the Token is stored on the client side in encrypted JSON form, JWT is cross-language in principle, and any web form supports it.

  • There is no need to save session information on the server side, which is especially suitable for distributed microservices.

3.2. Token composition

    1. Header

    The header usually consists of two parts: the type of token (i.e. JWT) and the signature algorithm used, such as HMAC SHA256 or RSA. It will use Base64 encoding to form the first part of the JWT structure

    1. Payload
    1. Signature

    The first two parts are encoded using Base64, that is, the front end can decrypt to know the information inside. The Signature needs to use the encoded header and payload and a secret key we provide, and then use the signature algorithm (HS256) specified in the header for signing. The role of the signature is to ensure that the JWT has not been tampered with

3.3 JWT encryption and decryption full process

@Test
void contextLoads() {
  Calendar instance = Calendar.getInstance();
  instance.add(Calendar.SECOND,100);
  String token = JWT.create()
          .withClaim("userid",12) 
          .withClaim("username", "xiaochen")//payload
          .withExpiresAt(instance.getTime())//specify token expiration time
          .sign(Algorithm.HMAC256("!Q@W#E$R"));//signature
  System.out.println(token);
}

@Test
public void test(){
  //Create verification object
  JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("!Q@W#E$R")).build();

  DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2OTYxMjg1MjMsInVzZXJpZCI6MTIsInVzZXJuYW1lIjoieGlhb2NoZW4ifQ.WhsEsCcf6c4hKr1eyhy6psQsaVIPr3Ibfqo3vM8sHKA\n");

  System.out.println(verify.getClaim("userid").asInt());
  System.out.println(verify.getClaim("username").asString());
  System.out.println("Expiration time: "+verify.getExpiresAt()); 
}

3.4 Common JWT exception information

  • SignatureVerificationException: Signature inconsistent exception

  • TokenExpiredException: Token expired exception

  • AlgorithmMismatchException: Algorithm mismatch exception

  • InvalidClaimException: Invalid payload exception

3.5 JWT encapsulation tool class

public class JWTUtils {

  private static final String SIGN = "!Q@W3e4r%T^Y";

  /**
   * Generate token header.payload.sign
   */
  public static String getToken(Map<String,String> map){

    Calendar instance = Calendar.getInstance();
    instance.add(Calendar.DATE,7);
    JWTCreator.Builder builder = JWT.create();
    map.forEach(builder::withClaim);
    return builder.withExpiresAt(instance.getTime()).sign(Algorithm.HMAC256(SIGN));
  }

  /**
   * Verify token validity, no exception means verification passed
   * Get payload in token
   *
   */
  public static DecodedJWT verify(String token){
    return JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
  }

}

Related

This article is licensed with Creative Commons Attribution 4.0 International License
Tag: Backend Spring Boot Spring Security
Last updated:2023-10-02

jimmychen

This person is a lazy dog and has left nothing

Like
< Last article
Next article >

Comments

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
Cancel

Archives
  • October 2023
  • September 2023
Categories
  • Algorithm
  • Android
  • Backend
  • Embedded
  • Security
Ads

COPYRIGHT © 2023 Tech Info. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang