Location>code7788 >text

Shiro Security Framework: The Best of Both Worlds

Popularity:718 ℃/2024-11-06 10:05:18

Apache Shiro is a powerful and flexible Java security framework focused on providing authentication, authorization, session management and encryption. It is often used to protect the access control of Java applications, especially in Web applications. Compared to Spring Security, Shiro's design is more concise, suitable for lightweight applications, and in many ways has a better ease of use and scalability, today V to talk about Shiro security framework.

Core Concepts of Shiro

As usual, let's take a look at the core concepts of Shiro with V:

  1. Subject
    Subject is a core interface in the Shiro framework that represents a "user" or "entity" in an application and is used to interact and store authentication state. It is usually accessed through the() Gets the current Subject, which represents the user's identity and permission data.

  2. SecurityManager
    SecurityManager is the core controller of Shiro and is responsible for managing all security operations and authentication. By configuring the SecurityManager, you can control the management of user authentication, authorization, sessions, and so on.

  3. Realm
    The Realm is the means by which Shiro obtains user, role, and permission information from data sources. By implementing a custom Realm, you can integrate Shiro with data sources such as databases, LDAP, files, etc. Shiro will fetch user authentication and authorization data from the Realm.

  4. Session
    Shiro comes with session management and does not depend on the session provided by the Servlet container. Shiro's session management can be used even in non-web environments. shiro's session management provides more granular controls such as session timeout, storage and sharing.

  5. Authentication
    Authentication is the process of verifying a user's identity. shiro provides simple APIs to implement the authentication process, such as(token)In practice, authentication is usually done through a combination of username and password. In practice, authentication is usually done through a combination of username and password, but Shiro also supports other methods (e.g. OAuth2, JWT, etc.).

  6. Authorization
    Authorization is the process of verifying that a user has certain permissions or roles. shiro supports both role-based and permission-based authorization, allowing for finer-grained control of permissions. Authorization is accomplished through the maybe method, developers can check the roles and permissions of users.

  7. Cryptography
    Shiro has built-in encryption features that provide support for encrypting and decrypting passwords and sensitive information. It supports a wide range of encryption algorithms and supports hashing and salting when storing passwords.

Key features and benefits of Shiro

V summarizes some of the main features and advantages of Shiro, which is used for bragging rights in interviews.

  1. Easy to integrate
    Shiro's API is designed to be simple and easy to integrate into a variety of Java applications. Developers can quickly build a basic security architecture based on the default implementation provided by Shiro, or customize various features as needed.

  2. Independent session management
    Unlike Web container-based session management, Shiro provides cross-environment session management that can be applied to both Web and non-Web environments, increasing application flexibility.

  3. Permission control is simple and flexible
    Shiro's permission management can be implemented through configuration files, annotations, or code, providing fine-grained access control. Through a combination of permissions and roles, developers can control access rights very flexibly.

  4. Supports multiple data sources
    Shiro can obtain user and permission information from a variety of data sources (e.g., databases, LDAP, files, etc.), facilitating integration with a variety of existing systems.

  5. Support for Web and non-Web environments
    Shiro can be used not only in web applications, but also in environments such as desktop applications or microservices.

Basic Shiro Usage Examples

It's not VG style to just talk about concepts, so let's walk through a typical Shiro application to see how to use it, including steps to configure SecurityManager, configure Realm, and perform authentication and authorization.

  1. Configuring the Shiro Environment
    This can be done by file to configure Shiro, or you can configure it through code.
   [main]
   # configure SecurityManager
   securityManager =

   # configure Realm
   myRealm =
    = $myRealm
  1. Creating a Custom Realm

    Customizing Realm by InheritanceAuthorizingRealm realizationdoGetAuthenticationInfo cap (a poem)doGetAuthorizationInfo method to provide user and permission data.

   public class MyCustomRealm extends AuthorizingRealm {
       @Override
       protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
           // Getting information such as username and password,Querying the database for authentication
           return new SimpleAuthenticationInfo(username, password, getName());
       }

       @Override
       protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
           // Getting information about user roles and permissions
           SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
           ("admin");
           ("user:read");
           return info;
       }
   }
  1. Authentication and Authorization with Shiro
   Subject currentUser = (); if (!
   currentUser = (); if (! ()) {
       UsernamePasswordToken token = new UsernamePasswordToken("username", "password"); try {
       try {
           (token); ("Authentication successful.
           ("Authentication Successful"); } catch (AuthenticationException a); ("Authentication Successful"); ("Authentication Successful")
       } catch (AuthenticationException ae) {
           ("Authentication failed"); } catch (AuthenticationException ae) { ("Authentication failed"); }
       }
   }

   // Checking permissions
   if (("admin")) {
       // Simulate this with the output haha
       ("The user has the admin role");
   }
   if (("user:read")) {
       // Simulate this with the output
       ("The user has the user:read permission"); }
   }

Through this simple case study, we can understand the basic use of Shiro, but that's not all, listen to V continue slowly.

Scenario Case

This is important to emphasize haha.Shiro is suitable for Java applications that require simplicity and ease of use, and flexibility in security control requirements, such as small and medium-sized Web applications, desktop applications, distributed microservices, etc. For large enterprise applications or projects that need to integrate multiple authentication methods (e.g. OAuth2, JWT, etc.), Spring Security may be more appropriate.

To implement Apache Shiro-based secure authentication and authorization in a microservices architecture, such as an order management system for example. This system contains two main services:

  1. customer service: Responsible for user registration, login, authentication and other operations.
  2. Order Service: Allow users to create, view, and delete orders and restrict access.

Let's see, how should this be designed?

Microservices Case Design

In this scenario, we need the following core functions:

  1. user authentication: The user logs in with a username and password.
  2. privilege control: Only administrators can delete orders, regular users can only view and create orders.
  3. Token Mechanism: Uses JWT Token (JSON Web Token) to manage the user's login state, realizing stateless authentication and making it independent of a single session in a distributed environment.
  4. Cross-service authentication: The Order Service checks and verifies the user's identity and permissions when it receives a request.

Architecture and technology selection

  • Spring Boot: For rapid building of microservices.
  • Shiro: Achieve authentication, authorization.
  • JWT: Generate and validate Token to maintain stateless authentication.
  • Spring Data JPA: Access to a database to store user and order data.

system structure

+------------------+ +---------------------+
| User Services | | Order Services | | Order Services
| | | | | | | |
| | User Registration, Login | | View, Create, Delete Orders | | | Order Service
+------------------+ +---------------------+
            
            |---- User Token ------|

Step: Implementing Authentication and Authorization in Microservices

1. Introduction of necessary dependencies

exist file, add dependencies such as Shiro, JWT, and Spring Data JPA:

<dependency>
    <groupId></groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.8.0</version>
</dependency>

<dependency>
    <groupId></groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
</dependency>

2. Configuring Shiro and JWT Filters

Use Shiro's custom JWT filters to implement stateless authentication, authenticating users with a Token.

public class JwtFilter extends BasicHttpAuthenticationFilter {

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String token = ("Authorization");

        if ((token)) {
            return false;
        }

        try {
            // analyze JWT token
            JwtToken jwtToken = new JwtToken(token);
            getSubject(request, response).login(jwtToken);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

3. Implementation of customized Realm

customizableRealmThe JWT Token is used to obtain user and role information from the database and to perform stateless authentication using the JWT Token.

public class JwtRealm extends AuthorizingRealm {

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String jwtToken = (String) ();

        // validate (a theory) Token
        String username = (jwtToken);
        if (username == null) {
            throw new AuthenticationException("Token null");
        }

        // user search
        User user = (username);
        if (user == null) {
            throw new AuthenticationException("The user does not exist");
        }

        return new SimpleAuthenticationInfo(jwtToken, jwtToken, getName());
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (());

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        User user = (username);

        // Adding roles and permissions
        (());
        (());

        return authorizationInfo;
    }
}

4. Create the JWT tool class

Write a tool class for generating and parsing JWT Token.

public class JwtUtil {

    //Replace your own heresecret_key
    private static final String SECRET_KEY = "It's coded here.";

    public static String generateToken(String username) {
        return ()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(() + 3600000)) // 1 hour
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }

    public static String getUsernameFromToken(String token) {
        Claims claims = ()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
        return ();
    }

    public static boolean isTokenExpired(String token) {
        Claims claims = ()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
        return ().before(new Date());
    }
}

5. Write user service and order service interfaces

User Service Interface

The user service provides registration and login APIs.

@RestController
@RequestMapping("/user")
public class UserController {

    @PostMapping("/register")
    public ResponseEntity<?> register(@RequestBody User user) {
        (user);
        return ("User Registration Successful");
    }

    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody User user) {
        User dbUser = (());
        if (dbUser != null && ().equals(())) {
            String token = (());
            return (token);
        }
        return ().body("Login Failure");
    }
}
Order Service Interface

The Order Service validates user roles and permissions when operating an order.

@RestController
@RequestMapping("/order")
public class OrderController {

    @GetMapping("/{orderId}")
    public ResponseEntity<?> getOrder(@PathVariable Long orderId) {
        Subject currentUser = ();
        if (("order:read")) {
            // Check Orders
            return ("Order Details");
        }
        return ().body("No permission to view orders");
    }

    @DeleteMapping("/{orderId}")
    public ResponseEntity<?> deleteOrder(@PathVariable Long orderId) {
        Subject currentUser = ();
        if (("admin")) {
            // Delete Order
            return ("Order Deleted");
        }
        return ().body("无权限Delete Order");
    }
}

ultimate

In this case we go through how to use Shiro, JWT and Spring Boot to build a stateless microservice authentication and authorization mechanism. We use Shiro for user authentication and privilege control and JWT for stateless token validation. In the lightweight distributed microservice applications, is not the use of Shiro feel more refreshing it, welcome to discuss the comments section, pay attention to Wei brother love programming, love Java, life.