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");