Shiro initializes authorization from the database

Keywords: Shiro Database xml Spring

According to the previous understanding, this time privilege-based authorization is implemented by initializing authorization from the database.

1. Analyse Shiro filter chain

    <! - Some interception rules for shiro configuration must have the same id as the shiro interceptor name in web.xml - >
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    	<! - Shiro's core security interface, this property is necessary - > Shiro's core security interface.  
		<property name="securityManager" ref="securityManager" />
		<! - If the authentication fails, jump to the configuration of the login page - > 
		<property name="loginUrl" value="/login" />  
		<! - After successful login page - >
		<property name="successUrl" value="/admin/index" />  
		<! - If the authentication fails, jump to the specified page - >. 
		<property name="unauthorized Url" value="/unauthorized"/> <!--page jumped after accessing unauthorized pages after login - >"
		<! -- Shiro Connection Constraint Configuration, the Definition of Filter Chain - >  
		<property name="filterChainDefinitions">
			<value>
				<! - Note: The rules are orderly. From top to bottom, the interception range must be small to large.
				 url = interception rule (anon is anonymous, authc is to be logged in before access, logout logout filtering) --> ____________
				/login = anon
				/logout = logout
				/admin/userlist = perms[userlist]
				/admin/addUser = perms[addUser]
				/admin/** = authc    
				/**= anon  
			</value>
		</property> 
	</bean>

Click on the filter Chain Definitions property to see the source code

1) You can see that it is an attribute of ShiroFilterFactoryBean:

    

2) After a series of initialization, it calls the setFilterChain DefinitionMap method and opens the method:

     

3) Through debug, you can see that filter Chain Definition Map is a LinkedHashMap when initializing, and its content is what we configure in the configuration file.

   

So we can configure a separate bean filter Chain Definition Map as an attribute of ShiroFilterFactoryBean.
Then we generate Map instances registered by instance factories, and then we need to build and configure a new Bean.

2. After analysis, modify spring.xml

Database:

Put authorization information in the database (pre-constraint, perms use p: roles use r:)

       

The other tables remain the same as before.

User admin, which only has roles admin and user and permission resources to access / admin/userlist, is accessible if pid is 3 and 4.

Note: The data order of t_permission: From top to bottom, the interception range must be small to large.

1) Configuring bean s

    <! - Some interception rules for shiro configuration must have the same id as the shiro interceptor name in web.xml - >
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    	<! - Shiro's core security interface, this property is necessary - > Shiro's core security interface.  
		<property name="securityManager" ref="securityManager" />
		<! - If the authentication fails, jump to the configuration of the login page - > 
		<property name="loginUrl" value="/login" />  
		<! - After successful login page - >
		<property name="successUrl" value="/admin/index" />  
		<! - If the authentication fails, jump to the specified page - >. 
		<property name="unauthorized Url" value="/unauthorized"/> <!--page jumped after accessing unauthorized pages after login - >"
		<property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"></property>
		<! -- Shiro Connection Constraint Configuration, the Definition of Filter Chain - >  
		<!-- <property name="filterChainDefinitions">
			<value>
				Note: The rules are orderly. From top to bottom, the interception range must be small to large.
				 url = interception rule (anon is anonymous, authc is accessible only after logout is filtered)
				/login = anon
				/logout = logout
				/admin/userlist = perms[userlist]
				/admin/addUser = perms[addUser]
				/admin/** = authc    
				/**= anon  
			</value>
		</property> -->
    </bean>

	<! - Configuration of beans through instance factory pattern: Configuring a bean injection is a Map instance - >
	<bean id="filterChainDefinitionMap" factory-bean="filterChainDefinitionMapFactory" factory-method="getFilterChainDefinitionMap"></bean>
	<bean id="filterChainDefinitionMapFactory" class="cn.jq.ssm.service.shiro.FilterChainDefinitionMapFactory"></bean>

2) Create this bean

import cn.jq.ssm.dao.PermissionMapper;
import cn.jq.ssm.model.Permission;

public class FilterChainDefinitionMapFactory {

	@Autowired
	private PermissionMapper permissionMapper;
	
	public Map<String, String> getFilterChainDefinitionMap(){
		//Getting data from a database
		List<Permission> permissions = permissionMapper.getAllPermissions();
		
		LinkedHashMap<String, String> permsMap = new LinkedHashMap<>();
		
		for (Permission permission : permissions) {
			if(permission.getPname().contains("p:")) {
				//Construct perms[userlist]
				String perms = permission.getPname().replace("p:", ""); //Delete prefix
				permsMap.put(permission.getUrl(), "perms["+ perms +"]");
			}else {
				permsMap.put(permission.getUrl(), permission.getPname());
			}
		}
		
		return permsMap;
	}
}

PermissionMapper method:

	<select id="getAllPermissions" resultType="cn.jq.ssm.model.Permission">
		select
			p.id,p.pname,p.url
		from 
			 t_permission p
	</select>

3) Customize ShiroRealm class and handle constraints p:

public class ShiroRealm extends AuthorizingRealm{
	/*
	 * public class ShiroRealm extends AuthenticatingRealm{
	 */
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private RoleMapper RoleMapper;
	@Autowired
	private PermissionMapper permissionMapper;
	/**
	 *  The method of login authentication in shiro
	 * @param token
	 * @return
	 * @throws AuthenticationException
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken token2 = (UsernamePasswordToken) token;
		String username = token2.getUsername();
		User user = userMapper.getUserByUsername(username);
		if(user == null) {
			throw new UnknownAccountException("Error in username or password!");
		}
		if(user.getStatus() == 0) {
			throw new UnknownAccountException("User name has been disabled, please contact the system administrator!");
		}
		
		/**
		 * principals: User name, or d, can be used to log in to the user's object
		 * hashedCredentials: Passwords retrieved from the database
		 * credentialsSalt: Salt Value of Cryptographic Encryption
		 * RealmName:  Class name (Shiro Realm)
		 */
		ByteSource credentialsSalt = ByteSource.Util.bytes("JQSalt");
		AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPazzword(), credentialsSalt, getName());
		return info;
	}
	
	/**
	 * Approaches to Authorization in shiro
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {		
		
		//1 Get the user information after the current successful login from the parameter principals
		User user = principals.oneByType(User.class);
		//2. Obtain the role information according to the user information in the first step (if the user information contains the role/authority information, take it out directly, if not, get it from the database)
		Set<String> roles = RoleMapper.getRolesByUserid(user.getId());
		// Obtain role-related permisssion information through user-related role information
		Set<String> permissions = permissionMapper.getPermissionsByUserid(user.getId());
		
		Set<String> newPermissions = new HashSet<>();
		for (String permission : permissions) {
			if(permission.contains("p:")) {
				//Delete the Convention prefix
				newPermissions.add(permission.replaceAll("p:", ""));
			}else {
				newPermissions.add(permission);
			}
		}
		
		//3 Inject the acquired role and privilege resource information associated with the logged-in user into the returned SimpleAuthorizationInfo object
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.addRoles(roles);
		info.addStringPermissions(newPermissions);
		return info;
	}

}

3. Login access project:

The results are consistent with the analysis.

        

end ~

 

 

Posted by ticallian on Sat, 27 Apr 2019 02:00:35 -0700