Detailed process of spring boot integrating shiro and session

Keywords: Java Spring Spring Boot

1. Dependence

      <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.7.1</version>
        </dependency>
               <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.7.1</version>
        </dependency>

2. Configuration

Configure security manager:

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

Which URLs need to be intercepted and which do not need to be intercepted. The login page, the url of the login success page, the custom Realm and other information need to be set in Shiro
shiro filter configuration:

 /**
     * 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 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");
 //Add your own path and access rights
        // System permission list
        // filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());

        Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
        filters.put("onlineSession", onlineSessionFilter());
        filters.put("syncOnlineSession", syncOnlineSessionFilter());
        filters.put("captchaValidate", captchaValidateFilter());
        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;
    }

The security manager associates its own Realm

  @Bean(name="security")
    public DefaultWebSecurityManager getDefaultManager(@Qualifier("realm")UserRealm userRealm){
     DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
     //Associate your own realm
        defaultSecurityManager.setRealm(userRealm);
        return defaultSecurityManager;
    }
    @Bean(name = "realm")
    //Create a realm object
    public UserRealm userRealm(){
        return new UserRealm();
    }

You can also associate more custom managers

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

 /**
     * 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;
        }
    }

You can also customize the session factory:

//Custom sessionFactory session
@Component
public class OnlineSessionFactory implements SessionFactory
{
    @Override
    public Session createSession(SessionContext initData)
    {
        OnlineSession session = new OnlineSession();
        if (initData != null && initData instanceof WebSessionContext)
        {
            WebSessionContext sessionContext = (WebSessionContext) initData;
            HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();
            if (request != null)
            {
                UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
                // Get client operating system
                String os = userAgent.getOperatingSystem().getName();
                // Get client browser
                String browser = userAgent.getBrowser().getName();
                session.setHost(IpUtils.getIpAddr(request));
                session.setBrowser(browser);
                session.setOs(os);
            }
        }
        return session;
    }
}

Record user information when logging in

At the controller level:

   @ApiOperation(value="Sign in")
@PostMapping("/login")
    public ResponseResult<User> toLogin(@ApiParam(name="User object",value="afferent json format",required=true)LoginForm loginForm)
{
   

    User user = userService.selectUserByLoginName(loginForm.getUserName(),loginForm.getPassword(), false);
  
    if (user != null) {
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(),user.getPassword(), false);
    Subject subject = SecurityUtils.getSubject();
subject.login(token);
return ResponseResult.success();}
    else return ResponseResult.error();
}

shiro some tool classes

SecurityUtils.getSubject() creates a subject for each request and saves it to the resources (ThreadLocal < map < object, Object > >) variable of ThreadContext, that is, a subject for an http request and bound to the current thread.
After the subject.login() login authentication is successful, how do you know which user is the next request?
Internal principle: one request and one Subject principle: since ShiroFilterFactoryBean is essentially an AbstractShiroFilter filter, the createSubject method in doFilterInternal will be executed for each request.
Source code:

public interface Subject {
    Object getPrincipal();

    PrincipalCollection getPrincipals();

    boolean isPermitted(String var1);

    boolean isPermitted(Permission var1);
    ...Omit other methods}
    

public interface SecurityManager extends Authenticator, Authorizer, SessionManager {
    Subject login(Subject var1, AuthenticationToken var2) throws AuthenticationException;

    void logout(Subject var1);

    Subject createSubject(SubjectContext var1);
}

public abstract class SecurityUtils {
    private static volatile SecurityManager securityManager;

    public SecurityUtils() {
    }

    public static Subject getSubject() {
        Subject subject = ThreadContext.getSubject();
        if (subject == null) {
            subject = (new Builder()).buildSubject();
            ThreadContext.bind(subject);
        }

        return subject;
    }

    public static void setSecurityManager(SecurityManager securityManager) {
        SecurityUtils.securityManager = securityManager;
    }

    public static SecurityManager getSecurityManager() throws UnavailableSecurityManagerException {
        SecurityManager securityManager = ThreadContext.getSecurityManager();
        if (securityManager == null) {
            securityManager = SecurityUtils.securityManager;
        }

        if (securityManager == null) {
            String msg = "No SecurityManager accessible to the calling code, either bound to the " + ThreadContext.class.getName() + " or as a vm static singleton.  This is an invalid application configuration.";
            throw new UnavailableSecurityManagerException(msg);
        } else {
            return securityManager;
        }
    }
}

shiro built-in session
session.setAttribute("username", username) is to save username into the session. The key value of the session is username, and its information (value) is username or reference value. In this way, this object can be obtained later through the method of session.getAttribute("username"). Usually, after the user has logged in to the system, a user information object can be stored in the session. The server can take this object out of the session at any time for some operations, such as authentication and so on.

request.getSession() can obtain an object of type HttpSession, which is usually called a session object. The scope of the session object is a session. Usually, the saved value will not disappear until the browser is closed. Of course, there will be a session timeout. The server can set the session timeout. There is a place for session time out in web.xml. tomcat defaults to 30 minutes.
session. setAttribute("key", value) is the method of setting the value of session. The principle is the same as that of Map set.
The return value type of getAttribute is Object, which needs to be transformed down to your userName type. For example, String session1= (String)session.getAttribute("student");

Posted by Hell Toupee on Thu, 02 Sep 2021 16:36:38 -0700