shiro security framework

Common security framework

  1. apache shhiro
    can be applied to any application system and does not depend on the spring framework.
    Simple and easy to get started.
    Generally used in traditional SSM applications.
  2. Springsecurity
    is one of the modules of the spring framework and must depend on the spring system.
    More powerful and complex,
    generally used for distributed development of springboot+springcloud microservices

The goal of the security framework

  1. User authentication user login
  2. Control of resource authority management authority (role)

The architecture of the shiro framework

Insert picture description here
Description:

  1. Security Manager Security Manager
  2. Authenticator authenticator user verification (login)
  3. Authorizer authority management (control)
  4. Session Manager The session manager manages the session and further manages the session
  5. Session DAO maintains session data
  6. Cache Manager is used for cache management of menu data
  7. Cryptography provides encryption algorithms for passwords, for example, MD5
  8. Realms means "realms". Mainly encapsulate the components of the business logic of authentication and authorization. (System realm or custom realm)
  9. Subject verification subject, individual, application, app

The certification process of shiro framework

Insert picture description here

Shiro user authentication

Implementation steps of the entry program

  • Import shiro's jar library
    Insert picture description here
  • Add shiro configuration file *.ini
    syntax:
    – [users] defines the user list
    – [main] the "root" of the container corresponding to the ini configuration file, which is equivalent to applicationContext.xml
  • Test code
	@Test  //入门认证: 使用默认的realm
	public void testLoginAndLogout() {
    
    
		
		Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-first.ini");
		SecurityManager securityManger = factory.getInstance();
		//构建securityManger环境
		SecurityUtils.setSecurityManager(securityManger);
		//获取认证的主体
		Subject subject = SecurityUtils.getSubject();
		
		//封装认证的令牌
		UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "111111");
		try {
    
    
			subject.login(token);   // 使用默认的系统的realm做用户认证。
		} catch (AuthenticationException e) {
    
    
			e.printStackTrace();
		}
		
		System.out.println("是否认证成功:" + subject.isAuthenticated());
		
		subject.logout();
		
		System.out.println("是否认证成功:" + subject.isAuthenticated());
		
	}

Result:
Account error: org.apache.shiro.authc.UnknownAccountException
Password error: org.apache.shiro.authc.IncorrectCredentialsException

  • Custom realm
package com.gec.shiro.realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

//需继承AuthorizingRealm
public class CustomRealm extends AuthorizingRealm {
    
    
	//执行认证
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    
    
		//先获取用户的帐号
		String username = (String) token.getPrincipal();
		
		//伪代码
//		User loginUser = userService.findUserByusername(username);
//		if(loginUser == null) {
    
    
//			return null;   //报异常:UnknownAccountException
//		}
//		String password_db = loginUser.getPassword();
		
		String username_db = "zhangsan";
		if(!username.equals(username_db)){
    
    
			return null;
		}
		String password_db = "111111";
		
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password_db, "CustomRealm");
		return info;
	}
	
	//执行授权
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
    
    
		// TODO Auto-generated method stub
		return null;
	}
}

Shiro's permission management

1. The authorization ID required by the request URI needs to be specified in the configuration file

	<property name="filterChainDefinitions">
		<value>
			<!-- 所有的静态资源要匿名访问 -->
				/bootstrap/**=anon
			    /css/**=anon
			    /js/**=anon
			    /static/**=anon
			    /images/**=anon
			    /styles/**=anon
			    <!-- 授权过滤器  , 建议使用注解授权或在jsp页面使用标签-->
			    /apply_baoxiao.jsp=perms[baoxiao:apply]
			    /myBaoxiaoBill=perms[baoxiao:billquery]
			    /myTaskList=perms[baoxiao:tasklist]
			    /add_process.jsp=perms[baoxiao:publish]
			    /processDefinitionList=perms[baoxiao:processlist]
			    /findUserList=perms[user:query]
			    /toAddRole=perms[user:create]
			    /findRoles=perms[baoxiao:rolelist]
			  	 
			  	 
			    /first=user
			    <!-- 退出系统 -->
			    /logout=logout
				/**=authc
				
			</value>
		</property>				

2. Authorize users in the custom Realm

	//权限授予
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
    
    	
		//从主体中获取用户信息
		ActiveUser activeUser = (ActiveUser) principal.getPrimaryPrincipal();
		List<SysPermission> permissions = null;
		try {
    
    
			//从数据库中查找用户的权限信息
			permissions = sysService.findPermissionListByUserId(activeUser.getUsercode());
		} catch (Exception e) {
    
    
			e.printStackTrace();
		}
		List<String> percodes = new ArrayList<>();
		for (SysPermission sysPermission : permissions) {
    
    
			//获取权限信息里的权限标识并加入列表
			percodes.add(sysPermission.getPercode());
		}
		//把权限列表授权给用户
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.addStringPermissions(percodes);
		return info;
	}

Integrated application of shiro and ssm

The basic configuration is as follows:

  • web.xml
	<!-- shiro的filter -->
	<!-- shiro过虑器,DelegatingFilterProxy通过代理模式将spring容器中的bean和filter关联起来 -->
	<filter>
		<filter-name>shiroFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
		<!-- 设置true由servlet容器控制filter的生命周期 -->
		<init-param>
			<param-name>targetFilterLifecycle</param-name>
			<param-value>true</param-value>
		</init-param>
		<!-- 设置spring容器filter的bean id,如果不设置则找与filter-name一致的bean -->
		<init-param>
			<param-name>targetBeanName</param-name>
			<param-value>shiroFilter</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>shiroFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
  • Configuration of applicationContext.xml spring file
	<!-- 开启aop,对类代理 -->
	<aop:config proxy-target-class="true"></aop:config>
	<!-- 开启shiro注解支持 -->
	<bean  class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
		<property name="securityManager" ref="securityManager" />
	</bean>

	<!-- web.xml中shiro的filter对应的bean -->
	<!-- Shiro 的Web过滤器 -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<!-- loginUrl认证提交地址,如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 -->
		<property name="loginUrl" value="/login.action" />
		<!-- 认证成功统一跳转到first.action,建议不配置,shiro认证成功自动到上一个请求路径 -->
		<property name="successUrl" value="/first.action" />
		<!-- 通过unauthorizedUrl指定没有权限操作时跳转页面 -->
		<property name="unauthorizedUrl" value="/refuse.jsp" />		
		<!-- 自定义filter配置 -->
		<property name="filters">
			<map>
				<!-- 将自定义 的FormAuthenticationFilter注入shiroFilter中-->
				<entry key="authc" value-ref="formAuthenticationFilter" />
			</map>
		</property>
		<!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边  -->
		<property name="filterChainDefinitions">
			<value>
			    <!-- 所有的静态资源要匿名访问 -->
			    /js/**=anon
			    /images/**=anon
			    /styles/**=anon
			    /validatecode.jsp=anon
			    
			    /items/queryItem.action=perms[item:query]
			    /items/editItems.action=perms[item:update]
			    
			    <!-- 退出系统 -->
			    /logout.action=logout
			    
				/**=authc
				
			</value>
		</property>
	</bean>

	<!-- securityManager安全管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="customRealm" />
		<property name="cacheManager" ref="cacheManager"/>
	</bean>

	<!-- realm -->
	<bean id="customRealm" class="cn.items.ssm.shiro.CustomRealm">
		<property name="credentialsMatcher" ref="credentialsMatcher" />
	</bean>
	
	<!-- 凭证匹配器 -->
	<bean id="credentialsMatcher"
		class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
		<property name="hashAlgorithmName" value="md5" />
		<property name="hashIterations" value="2" />
	</bean>
	
     <!-- 自定义form认证过虑器 -->
	<!-- 基于Form表单的身份验证过滤器,不配置将也会注册此过虑器,表单中的用户账号、密码及loginurl将采用默认值,建议配置 -->
	<bean id="formAuthenticationFilter" class="cn.items.ssm.shiro.CustomFormAuthenticationFilter">
		<!-- 表单中账号的input名称 -->
		<property name="usernameParam" value="username" />
		<!-- 表单中密码的input名称 -->
		<property name="passwordParam" value="password" />
   </bean>
    
    <!-- 缓存管理器 -->
	<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    	<property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/>
    </bean>

Sketch of the user authentication process:
Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_45879810/article/details/108770571