[ruoyi] learning notes on open source framework 02 - Shiro permission framework

Posted by bk6662 on Fri, 18 Feb 2022 13:16:29 +0100

data

↑ the link of Shiro document is an official introduction to the quick start. In fact, it will be easier to understand ruoyi's document about the integration of the framework.

If according to the structure

1. Security Manager

The Subject body represents the current "user". This user is not necessarily a specific person. Anything interacting with the current application is a Subject, such as web crawler, robot, etc; An abstract concept; All subjects are bound to the SercurityManager, and all interactions with subjects will be delegated to the SecurityManager; You can think of Subject as a facade; The SecurityManager is the actual executor
SecurityManage security manager; That is, all security related operations will interact with SecurityManager; And it manages all subjects; It can be seen that it is the core of Shiro, which is responsible for interacting with other components introduced later

Security Manager SecurityManager (com.ruoyi.framework.config.ShiroConfig)

/**
 * Security Manager
 */
@Bean
public SecurityManager securityManager(UserRealm userRealm)
{
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    // Set realm
    securityManager.setRealm(userRealm);
    // Remember me
    securityManager.setRememberMeManager(rememberMeManager());
    // Injection cache manager;
    securityManager.setCacheManager(getEhCacheManager());
    // session manager
    securityManager.setSessionManager(sessionManager());
    return securityManager;
}

According to the framework, the main parameters of SecurityManager include Realm, memberme, CacheManager, SessionManager, etc.

2. Realm

To obtain the user's identity from realmro, i.e. whether it needs to verify the user's identity from realmro; You also need to get the corresponding role / authority of the user from Realm to verify whether the user can operate; There can be one or more realms. We generally need to implement our own realms in our applications

Ruoyi also implements its own Realm (com.ruoyi.framework.shiro.realm.UserRealm) in the framework. In the custom Realm, it mainly rewrites two methods: doGetAuthorizationInfo (authorization) and doGetAuthenticationInfo (login authentication).

And real is added to the cache manager (com.ruoyi.framework.config.ShiroConfig).

/**
 * Custom Realm
 */
@Bean
public UserRealm userRealm(EhCacheManager cacheManager)
{
    UserRealm userRealm = new UserRealm();
    userRealm.setAuthorizationCacheName(Constants.SYS_AUTH_CACHE);
    userRealm.setCacheManager(cacheManager);
    return userRealm;
}

3. SessionManager,SessionDAO,SessionFactory

If the SessionManager has written servlets, it should know the concept of session. Session needs someone to manage its life cycle. This component is SessionManager
Session daodao has been used by everyone. Database access objects and CRUD for sessions. For example, if we want to save sessions to the database, we can implement our own SessionDAO or write to the cache to improve performance

SessionManager (com.ruoyi.framework.config.ShiroConfig)

/**
 * Session manager
 */
@Bean
public OnlineWebSessionManager sessionManager()
{
    OnlineWebSessionManager manager = new OnlineWebSessionManager();
    // Join cache manager
    manager.setCacheManager(getEhCacheManager());
    // Delete expired session s
    manager.setDeleteInvalidSessions(true);
    // Set global session timeout
    manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
    // Remove JSESSIONID
    manager.setSessionIdUrlRewritingEnabled(false);
    // Define an invalid Session timing scheduler to use
    manager.setSessionValidationScheduler(SpringUtils.getBean(SpringSessionValidationScheduler.class));
    // Whether to check the session regularly
    manager.setSessionValidationSchedulerEnabled(true);
    // Customize SessionDao
    manager.setSessionDAO(sessionDAO());
    // Custom sessionFactory
    manager.setSessionFactory(sessionFactory());
    return manager;
}

SessionFactory (com.ruoyi.framework.config.ShiroConfig)

/**
 * Customize sessionFactory sessions
 */
@Bean
public OnlineSessionFactory sessionFactory()
{
    OnlineSessionFactory sessionFactory = new OnlineSessionFactory();
    return sessionFactory;
}

Customize sessionFactory session OnlineSessionFactory (com.ruoyi.framework.shiro.session.OnlineSessionFactory)
It mainly obtains the required information from the request and saves it to the user-defined object OnlineSession.

SessionDAO (com.ruoyi.framework.config.ShiroConfig)

/**
 * Custom sessionDAO sessions
 */
@Bean
public OnlineSessionDAO sessionDAO()
{
    OnlineSessionDAO sessionDAO = new OnlineSessionDAO();
    return sessionDAO;
}

OnlineSessionDAO (com.ruoyi.framework.shiro.session.OnlineSessionDAO) db operation for custom ShiroSession.

4. Cache manager

CacheManager cache controller to manage the cache of users, roles, permissions, etc; Because these data are rarely changed, putting them in the cache can improve the performance of access

EhCacheManager (com.ruoyi.framework.config.ShiroConfig)
If EhCacheManager is used according to the cache configuration in the framework, the configuration file is ehcache Shiro xml .

/**
 * The cache manager is implemented using Ehcache
 */
@Bean
public EhCacheManager getEhCacheManager()
{
    net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("ruoyi");
    EhCacheManager em = new EhCacheManager();
    if (StringUtils.isNull(cacheManager))
    {
        em.setCacheManager(new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream()));
        return em;
    }
    else
    {
        em.setCacheManager(cacheManager);
        return em;
    }
}

/**
 * Return the configuration file stream to prevent the ehcache configuration file from being occupied all the time, and the project cannot be completely destroyed and redeployed
 */
protected InputStream getCacheManagerConfigFileInputStream()
{
    // shiro cache profile path
    String configFile = "classpath:ehcache/ehcache-shiro.xml";
    InputStream inputStream = null;
    try
    {
        inputStream = ResourceUtils.getInputStreamForPath(configFile);
        byte[] b = IOUtils.toByteArray(inputStream);
        InputStream in = new ByteArrayInputStream(b);
        return in;
    }
    catch (IOException e)
    {
        throw new ConfigurationException(
                "Unable to obtain input stream for cacheManagerConfigFile [" + configFile + "]", e);
    }
    finally
    {
        IOUtils.closeQuietly(inputStream);
    }
}

5. Configure ShiroFilterFactoryBean for Shiro filter

ShiroFilterFactoryBean (com.ruoyi.framework.config.ShiroConfig)

/**
 * Shiro Filter configuration
 */
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
{
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    // Shiro's core security interface, this attribute is required
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    // If the authentication fails, you will jump to the configuration of the login page
    shiroFilterFactoryBean.setLoginUrl(loginUrl);
    // If the authority authentication fails, jump to the specified page
    shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
    // Shiro connection constraint configuration, that is, the definition of filter chain
    LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
    // Set anonymous access to static resources
    filterChainDefinitionMap.put("/favicon.ico**", "anon");
    filterChainDefinitionMap.put("/ruoyi.png**", "anon");
    filterChainDefinitionMap.put("/html/**", "anon");
    filterChainDefinitionMap.put("/css/**", "anon");
    filterChainDefinitionMap.put("/docs/**", "anon");
    filterChainDefinitionMap.put("/fonts/**", "anon");
    filterChainDefinitionMap.put("/img/**", "anon");
    filterChainDefinitionMap.put("/ajax/**", "anon");
    filterChainDefinitionMap.put("/js/**", "anon");
    filterChainDefinitionMap.put("/ruoyi/**", "anon");
    filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
    // Exit logout address and shiro to clear session
    filterChainDefinitionMap.put("/logout", "logout");
    // Access that does not need to be blocked
    filterChainDefinitionMap.put("/login", "anon,captchaValidate");
    // Registration related
    filterChainDefinitionMap.put("/register", "anon,captchaValidate");
    // System permission list
    // filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());

    Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
    // Customize online user processing filters
    filters.put("onlineSession", onlineSessionFilter());
    // Customize online user synchronization filter
    filters.put("syncOnlineSession", syncOnlineSessionFilter());
    // Custom verification code filter
    filters.put("captchaValidate", captchaValidateFilter());
    // Multiple device login restrictions for the same user
    filters.put("kickout", kickoutSessionFilter());
    // If the logout is successful, jump to the specified page
    filters.put("logout", logoutFilter());
    shiroFilterFactoryBean.setFilters(filters);

    // All requests require authentication
    filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

    return shiroFilterFactoryBean;
}

Topics: Java Shiro