Combination of Apache Shiro and Spring boot

In fact, it is most suitable to use Spring Security in Spring boot. After all, it is its own thing. The most important point is that Spring Security has its own csrf filter to prevent csrf attacks, but not in Shiro.

But Spring Security is a bit too complicated, and it is more laborious to custmize, not as simple as shiro.

If you want to use shiro in Spring boot, you need to perform the following configuration. First, add shiro dependencies in pom.xml.

 

		<dependency>
		    <groupId>org.apache.shiro</groupId>
		    <artifactId>shiro-spring</artifactId>
		    <version>1.2.5</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.shiro</groupId>
		    <artifactId>shiro-ehcache</artifactId>
		    <version>1.2.5</version>
		</dependency>
		<dependency>
		    <groupId>com.github.theborakompanioni</groupId>
		    <artifactId>thymeleaf-extras-shiro</artifactId>
		    <version>1.2.1</version>
		</dependency>

 Shiro officially only provides jsp tags, not thymeleaf, and thymeleaf has been widely used in spring boot, and it relies on a third-party package.

 

Then there is the configuration file of shiro, here we use java-based configuration

 

@Configuration
public class ShiroConfiguration {
	
	@Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
	
	@Bean(name = "hashedCredentialsMatcher")
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
		credentialsMatcher.setHashAlgorithmName("MD5");
		credentialsMatcher.setHashIterations(2);
		credentialsMatcher.setStoredCredentialsHexEncoded(true);
		return credentialsMatcher;
	}
	
	@Bean(name = "shiroRealm")
	@DependsOn("lifecycleBeanPostProcessor")
    public ShiroRealm shiroRealm() {
		ShiroRealm realm = new ShiroRealm();
		realm.setCredentialsMatcher(hashedCredentialsMatcher());
        return realm;
    }
	
	@Bean(name = "ehCacheManager")
	@DependsOn("lifecycleBeanPostProcessor")
	public EhCacheManager ehCacheManager(){
		EhCacheManager ehCacheManager = new EhCacheManager();
		return ehCacheManager;
	}
	
	@Bean(name = "securityManager")
	public SecurityManager securityManager(){
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(shiroRealm());
		securityManager.setCacheManager(ehCacheManager());
		return securityManager;
	}

	@Bean(name = "shiroFilter")
	public ShiroFilterFactoryBean shiroFilterFactoryBean () {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean ();
		shiroFilterFactoryBean.setSecurityManager(securityManager());
		
		Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
		LogoutFilter logoutFilter = new LogoutFilter();
		logoutFilter.setRedirectUrl ("/ login");
		filters.put("logout", logoutFilter);
		shiroFilterFactoryBean.setFilters(filters);
		
		Map<String, String> filterChainDefinitionManager = new LinkedHashMap<String, String>();
		filterChainDefinitionManager.put("/logout", "logout");
		filterChainDefinitionManager.put("/user/**", "authc,roles[user]");
		filterChainDefinitionManager.put("/shop/**", "authc,roles[shop]");
		filterChainDefinitionManager.put("/admin/**", "authc,roles[admin]");
		filterChainDefinitionManager.put("/**", "anon");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager);
		
		shiroFilterFactoryBean.setLoginUrl("/login");
		shiroFilterFactoryBean.setSuccessUrl("/");
		shiroFilterFactoryBean.setUnauthorizedUrl("/403");
		
		return shiroFilterFactoryBean;
	}

	@Bean
	@ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
        daap.setProxyTargetClass(true);
        return daap;
    }
	
	@Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(securityManager());
        return aasa;
    }
	
	@Bean(name = "shiroDialect")
	public ShiroDialect shiroDialect(){
		return new ShiroDialect();
	}
}

 

  1.  LifecycleBeanPostProcessor, which is a subclass of DestructionAwareBeanPostProcessor, is responsible for the life cycle, initialization and destruction of beans of type org.apache.shiro.util.Initializable. Mainly a subclass of the AuthorizingRealm class, and the EhCacheManager class.
  2. HashedCredentialsMatcher, this class is to encode the password and prevent the password from being stored in the database in plain code. Of course, in the life of login authentication, this class is also responsible for encoding the password entered in the form.
  3. ShiroRealm, which is a custom authentication class, inherits from AuthorizingRealm and is responsible for user authentication and authorization processing. You can refer to the implementation of JdbcRealm.
  4. EhCacheManager, cache management, after the user logs in successfully, cache the user information and permission information, and then put it into the user's session every time the user requests. If this bean is not set, the database will be queried once for each request.
  5. SecurityManager, permission management, this class combines login, logout, permission, session processing, and is a more important class.
  6. ShiroFilterFactoryBean, is a factorybean, in order to generate ShiroFilter. It mainly maintains three items of data, securityManager, filters, filterChainDefinitionManager.
  7. DefaultAdvisorAutoProxyCreator, a bean of Spring, is used by Advisor to decide which class methods are AOP proxy.
  8. AuthorizationAttributeSourceAdvisor, the Advisor class implemented in shiro, uses AopAllianceAnnotationsAuthorizingMethodInterceptor internally to intercept methods annotated with the following. To be honest, I don't know what's the use of injecting securityManager here, and I can't see where it will be called from the source.
    private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =
            new Class[] {
                    RequiresPermissions.class, RequiresRoles.class,
                    RequiresUser.class, RequiresGuest.class, RequiresAuthentication.class
            };

 9. ShiroDialect, in order to use shiro's labeled bean in thymeleaf

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326802487&siteId=291194637