A comparison between Shiro and Spring Security

Shiro

Shiro is a powerful and flexible open source security framework that handles authentication, authorization, management sessions, and password encryption very clearly. The following are its characteristics:

  1. An easy-to-understand Java Security API;
  2. Simple authentication (login), support for multiple data sources (LDAP, JDBC, Kerberos, ActiveDirectory, etc.);
  3. Simple sign-off (access control) for roles, supporting fine-grained sign-off;
  4. Support level 1 caching to improve application performance;
  5. Built-in POJO-based enterprise session management for Both Web and non-Web environments;
  6. Heterogeneous client session access;
  7. Very simple encryption API;
  8. Does not bind to any framework or container and can run independently.

Spring Security

Shiro has all of its features except that it can’t be separated from Spring. Spring Security also supports Oauth and OpenID, while Shiro needs to implement it manually.

Personal opinion:

Shiro is easier to use, implement, and most importantly understand than Spring

The only reason Spring Security is better known is because of the brand name

“Spring” is known for its simplicity, but ironically many people find it difficult to install Spring Security

However, Spring Security has better community support

Apache Shiro has an additional module for Spring Security handling cryptography

Spring-security works well with Spring and is easy to use if your project uses SpringMVC. But if spring is not used in your project, forget it.

Shiro is powerful, simple, and flexible. Projects under Apache are more reliable, and do not bind to any framework or container, can run independently

What is Shiro?

(1) Functions: authentication, authorization, session management, encryption, cache management

Subject: the Subject can be any “user” that can interact with the application.

SecurityManager: equivalent to SpringMVC’s DispatcherServlet or Struts2’s FilterDispatcher; Is Shiro’s heart; All specific interactions are controlled through the SecurityManager; It manages all subjects and is responsible for authentication and authorization, as well as session and cache management.

Authenticator is an extension point. If you don’t like Shiro’s default, you can customize it. It needs an Authentication Strategy, that is, under what circumstances is the user authenticated;

Authrizer: the authorizer, or access controller, used to determine whether a principal has permission to perform the corresponding operation; It controls what functions users can access in the application;

Realm: There can be one or more realms, which can be considered a secure entity data source for obtaining secure entities. It could be a JDBC implementation, it could be an LDAP implementation, it could be an in-memory implementation, etc.; Provided by the user; Note: Shiro does not know where and in what format your users/permissions are stored; So we generally need to implement our own Realm in our applications;

SessionManager: If you’ve written servlets, you know the concept of a Session. A Session needs someone to manage its life cycle. This component is the SessionManager. Shiro can be used not only in the Web environment, but also in normal JavaSE environment, EJB environment, etc. Therefore, Shiro abstracts its own Session to manage the data that subjects interact with the application. In this case, let’s say we use it in the Web environment, we start with a Web server; Then it went to the EJB server; You can implement your own distributed session if you want to keep the session data from both servers in one place (for example, put the data on a Memcached server).

SessionDAO: Data access object, used for Session CRUD, for example, we want to save the Session to the database, then can implement their own SessionDAO, such as JDBC to write to the database; For example, if you want to put sessions into Memcached, you can implement your own Memcached SessionDAO. In addition, SessionDAO can use Cache for caching to improve performance;

CacheManager: Cache controller that manages caches of users, roles, and permissions. Because this data is rarely changed, putting it in the cache can improve access performance

Cryptography: A Cryptography module, Shiro provides some common encryption components for use such as password encryption/decryption.

(3) Internal architecture

Iii. Introduction of Shrio’s features

An easy-to-understand Java Security API

Simple authentication (login), support for multiple data sources (LDAP, JDBC, Kerberos, ActiveDirectory, etc.);

Simple sign-off (access control) for roles, supporting fine-grained sign-off;

Support level 1 caching to improve application performance;

Built-in POJO-based enterprise session management for Both Web and non-Web environments;

Heterogeneous client session access;

Very simple encryption API;

Does not bind to any framework or container and can run independently.

Start fast

1. Import dependencies

<dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.23.</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.725.</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.725.</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.217.</version>
        </dependency>
    </dependencies>
Copy the code

2. Configuration file

Create a log4j.properties file

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
log4j.logger.org.apache=WARN
log4j.logger.org.springframework=WARN
log4j.logger.org.apache.shiro=INFO
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN
Copy the code

(2) Configure the shiro. Ini file

[users]
root = secret, admin
guest = guest, guest
presidentskroob = 12345, president
darkhelmet = ludicrousspeed, darkload, schwartz
lonestarr = veespa, goodguy, schwartz
[roles]
admin = *
schwartz = lightsaber:*
goodguy = winnebago:drive:eagle5
Copy the code

3. Start fast

Step 1: Get the current object subject Step 2: Get the Session from the current user Step 3: Determine whether the current user is authenticated and set remember me and perform login operation Step 4: Test role Step 5: Check what the permissions look like: coarse and fine grained

public class QuickStart {
    private static final transient Logger log = (Logger) LoggerFactory.getLogger(QuickStart.class);
    public static void main(String[] args) {
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("claspath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        // Get the current object subject
        Subject currentUser = SecurityUtils.getSubject();
        // Get Session from the current user
        Session session = currentUser.getSession();
        session.setAttribute("someKey"."aValue");
        String value = (String) session.getAttribute("someKey");
        if(value.equals("aValue")){
            log.info("Subject**>session["+value+"]");
        }
        // Check whether the current user is authenticated
        if(! currentUser.isAuthenticated()){/ / Token, the Token
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr"."vespa");
            token.setRememberMe(true);// Set remember me
            // Perform the login operation
            try {
                currentUser.login(token);
            }catch (UnknownAccountException uae){
                log.info("没有"+token.getPrincipal()+"This username");
            }catch (IncorrectCredentialsException ice){
                log.info(token.getPrincipal()+"Password error");
            }catch (LockedAccountException lae){
                log.info(token.getPrincipal()+"Locked in"); }}// Test the role
        if (currentUser.hasRole("schwartz")){
            log.info("Character passes");
        }else{
            log.info("Wrong role");
        }
        // What are the permissions for detection: coarse-grained
        if (currentUser.isPermitted("lightsaber:*")){
            log.info("You can use Lightsaber.");
        }else{
            log.info("You can't use Lightsaber.");
        }
        // What are the permissions for detection: fine-grained
        if (currentUser.isPermitted("winnebago:drive:eagle5")){
            log.info("You can drive eagle5.");
        }else{
            log.info("You can't drive eagle5");
        }
        / / logout
        currentUser.logout();
        // Shut down the system
        System.exit(0); }}Copy the code
Write Shiro test classes

Running results:

Summary: Shiro remains powerful and easy to use compared to Spring Security, with huge advantages in simplicity and flexibility.