Explication détaillée de l'intégration du shiro et du ressort et solutions pour que les annotations de shiro dans le projet de printemps ne prennent pas effet

One, configuration shiro dans le projet de printemps

(1) configuration web.xml

<!-- shiro过滤器 -->
	<filter>
		<filter-name>shiroFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
		<init-param>
			<param-name>targetFilterLifecycle</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>shiroFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

(2) Configuration intégrée Shiro et ressort

<!-- 使用shiro安全检查注解 -->
	<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" />
	
	<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
		<property name="securityManager" ref="securityManager" />
	</bean>

	<!-- shiro的生命周期处理器 -->
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

	<!-- shiro自带的密码匹配器(用来校验密码足够了) -->
	 <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.SimpleCredentialsMatcher"></bean>  
	<!-- security datasource: -->
	<bean id="myRealm" class="cc.eguid.service.shiro.MyRealm">
		<property name="credentialsMatcher" ref="credentialsMatcher"/><!-- 密码匹配器 -->
        <property name="cachingEnabled" value="false"/><!-- 禁止缓存 -->
	</bean>
	<!-- 安全管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="myRealm" />
	</bean>
	<!-- shiro过滤器 -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<!-- 配置安全管理器 -->
		<property name="securityManager" ref="securityManager" />
		<!-- 身份认证失败跳转的地址 -->
		<property name="loginUrl" value="/login/" />
		<!-- 身份认证成功跳转的地址 -->
		<property name="successUrl" value="/" />
		<!-- 权限认证失败跳转的地址 -->
		<property name="unauthorizedUrl" value="/login/unauthorized" />
		<property name="filterChainDefinitions">
			<!--anon 表示匿名访问,不需要认证以及授权 -->
			<!--authc表示需要认证 没有进行身份认证是不能进行访问的 -->
			<!--authc,roles[admin]表示是admin角色的用户才能访问 -->
			<value>
				/static/** = anon
				/login/** = anon
				/common/** = anon
				/admin/** = authc,roles[admin]
				/* = authc
				/** = authc
			</value>
		</property>
	</bean>
	
	

Implémentation du vérificateur de mot de passe deux, royaume et personnalisé

1. Implémentation du royaume

public class MyRealm extends AuthorizingRealm{
	Logger log=Logger.getLogger(MyRealm.class);
	
	@Autowired
    private UserService userService;//这是自己实现的用户信息操作类,实现用户信息,用户角色信息、用户权限信息查询功能

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		UserInfo user = (UserInfo) principals.getPrimaryPrincipal();
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		// 查询角色信息
		Collection<String> roles = userService.findRoles(user);
		info.addRoles(roles);
		log.info("shiro获取用户所属角色列表:"+roles);
		// 查询权限信息
		Collection<String> permissions = userService.findPermissions(user.getSystemuserid());
		info.addStringPermissions(permissions);
		log.info("shiro获取用户权限列表:"+permissions);
		return info;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException{
		//用户输入的用户名密码
		String loginname=  token.getPrincipal().toString();
		Object password=token.getCredentials();
		log.info("shiro正在处理尝试登录的用户信息:"+loginname+",密码:"+new String((char[])password));
		//数据库中的用户信息
		UserInfo user =userService.queryUserInfoByLoginName(loginname);
		if(user==null||CommonUtil.isNull(user.getLoginusername(),user.getPassword(),user.getSystemuserid())){
			return null;
		}
		log.info("shiro获取到当前用户尝试登录的真实数据:"+user.getLoginusername()+",密码:"+user.getPassword());
		//数据库中的正确的账户信息
		AuthenticationInfo accountInfo =new SimpleAuthenticationInfo(user, user.getPassword(),getName());
				
		//自己获取密码验证器(由于shiro实现的密码校验方法是密码错误会直接抛异常,不采用,所以改成直接手动校验)
		CredentialsMatcher matcher=getCredentialsMatcher();
		if(matcher==null){
			log.error("没有配置密码匹配器");
			return null;
		}
		//校验密码
		if(matcher.doCredentialsMatch(token,accountInfo)){
			return accountInfo;//校验通过,返回账号信息
		}
		
		return null;
	}


}

2. Vérificateur de mot de passe personnalisé


/**
 * 自定义shiro密码匹配(密码是在md5散列值的基础上再次进行md5加盐操作,加盐值不保存在数据库,而是放在配置文件中)
 * @author eguid
 *
 */
public class MyCredentialsMatcher extends CodecSupport implements CredentialsMatcher {
	private static final Logger log = LoggerFactory.getLogger(MyCredentialsMatcher.class);

	protected Object getCredentials(AuthenticationToken token) {
		return token.getCredentials();
	}

	protected Object getCredentials(AuthenticationInfo info) {
		return info.getCredentials();
	}

	@Autowired
	private CommonConfigs commonConfigs;
	/**
	 * 验证密码
	 * 
	 * @param tokenCredentials
	 * @param accountCredentials
	 * @return
	 */
	protected boolean equals(Object tokenCredentials, Object accountCredentials) {
		if (log.isDebugEnabled()) {
			log.debug("Performing credentials equality check for tokenCredentials of type ["
					+ tokenCredentials.getClass().getName() + " and accountCredentials of type ["
					+ accountCredentials.getClass().getName() + "]");
		}
		if (isByteSource(tokenCredentials) && isByteSource(accountCredentials)) {
			if (log.isDebugEnabled()) {
				log.debug("Both credentials arguments can be easily converted to byte arrays.  Performing "
						+ "array equals comparison");
			}
			byte[] tokenBytes = toBytes(tokenCredentials);
			byte[] accountBytes = toBytes(accountCredentials);
			return MessageDigest.isEqual(tokenBytes, accountBytes);
		} else {
			return accountCredentials.equals(tokenCredentials);
		}
	}
	
	public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
		Object tokenCredentials = getCredentials(token);
		Object accountCredentials = getCredentials(info);
		String account=String.valueOf((char[])tokenCredentials);
		if(commonConfigs.getMd5salt()==null){
			if (log.isDebugEnabled()) {
				log.debug("配置文件中的加盐值为空,无法进行密码匹配,请确认配置文件是否在指定位置或配置指定加盐值");
			}
			return false;
		}
		String saltaccount=MD5Util.getMD5(account, commonConfigs.getMd5salt());
		if (log.isDebugEnabled()) {
			log.debug("加盐后的密码:"+saltaccount);
		}
		return equals(accountCredentials, saltaccount.toCharArray());
	}

}

3. Utilisation d'annotations et de balises de modèle (lorsque les annotations ne sont pas valides)

1. Utilisation des annotations

@RequiresPermissions ({"user: update: view"}) // Vérifier les autorisations d'opération

@RequiresPermissions (value = {"user: add", "user: view"}, logical = Logical.OR) // L'une des deux autorisations d'opération peut passer l'inspection si les conditions sont remplies

@RequiresRoles ({"admin"}) // Vérifier les rôles

@RequiresRoles (value = {"debug", "admin"}, logical = Logical.OR) // L'un des deux rôles peut remplir les conditions


@ RequiertAuthentication // Vérifiez si l'authentification shiro est passée
@ RequiertGuest // Aucune vérification requise
@ RequiertUser // Vérifiez si l'utilisateur est un utilisateur dans le système actuel


2. Utilisation des étiquettes

Pour utiliser des balises, vous devez d'abord importer la bibliothèque de balises de shiro <% @ taglib prefix = "shiro" uri = "http://shiro.apache.org/tags"%>

(1) Afficher les informations d'identité de l'utilisateur

<shiro: principal />
appelle Subject.getPrincipal () par défaut


<shiro: principal property = "username" />

Équivalent à ((User) Subject.getPrincipals ()). GetUsername ()


(2) Affiché par les utilisateurs shiro connectés

 <shiro: user>  
Bienvenue [<shiro: principal />] à se connecter, <a href="logout"> se déconnecter </a>  
< shiro: user>

(3) Accès utilisateur anonyme

<shiro: guest> Utilisateurs qui n'ont pas été vérifiés par shiro (invités, utilisateurs anonymes) </ shiro: guest>  


(4) Ceux qui se sont connectés à shiro (utilisateurs connectés)

 <shiro: authenticated> L'  
    utilisateur [<shiro: principal />] a été authentifié  
< shiro: authenticated> 

(5) Ceux qui ne se sont pas connectés à shiro

 <shiro: notAuthenticated>
    non authentifié (y compris se souvenir de moi)
< shiro: notAuthenticated>

(6) Vérifiez le rôle

 <shiro:hasRole name="admin">
    用户[<shiro:principal/>]拥有角色admin<br/>
< shiro:hasRole>

检查任意角色(其中一个满足条件即通过,相当于OR)
 <shiro:hasAnyRoles name="admin,user">
    用户[<shiro:principal/>]拥有角色admin或user<br/>
<sh iro:hasAnyRoles>

不具有角色(反向判断)
 <shiro:lacksRole name="abc">
    用户[<shiro:principal/>]不具有角色abc<br/>
< shiro:lacksRole>

(7)操作权限判断

 <shiro: hasPermission name = "user: create">  
    用户 [<shiro: principal />] 拥有 权限 utilisateur: create <br/>  
< shiro: hasPermission>    

Aucune autorité d'exploitation (jugement inversé)
 <shiro: lacksPermission name = "org: create">  
    用户 [<shiro: principal />] 没有 权限 org: create <br/>  
< iro: lacksPermission>  



Quatrièmement, l'annotation ne prend pas effet

Libérez l'annotation shiro pour la numérisation d'annotations de springMVC (c'est-à-dire, chargez-la dans le conteneur springMVC)

<!-- 使用shiro安全检查注解 -->
	<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" />
	
	<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
		<property name="securityManager" ref="securityManager" />
	</bean>
Scannez directement le shiro ci-dessus et placez-le dans le servlet-context.xml ci-dessous pour que l'annotation shiro prenne effet

<!-- springMVC应用 -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>2</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>






Je suppose que tu aimes

Origine blog.csdn.net/eguid/article/details/78337275
conseillé
Classement