Cadre de sécurité commun
- apache shhiro
peut être appliqué à n'importe quel système d'application et ne dépend pas de la structure du ressort.
Simple et facile à démarrer.
Généralement utilisé dans les applications SSM traditionnelles. - Springsecurity
est l'un des modules du cadre de ressort et doit dépendre du système de ressort.
Plus puissant et complexe,
généralement utilisé pour le développement distribué de microservices springboot + springcloud
L'objectif du cadre de sécurité
- Connexion utilisateur d'authentification utilisateur
- Contrôle de l'autorité de gestion de l'autorité de ressources (rôle)
L'architecture du cadre shiro
Description:
- Gestionnaire de sécurité Security Manager
- Vérification de l'utilisateur Authenticator Authenticator (connexion)
- Gestion de l'autorité d' autorisation (contrôle)
- Gestionnaire de session Le gestionnaire de session gère la session et gère en outre la session
- Session DAO conserve les données de session
- Cache Manager est utilisé pour la gestion du cache des données de menu
- La cryptographie fournit des algorithmes de cryptage pour les mots de passe, par exemple MD5
- Realms signifie "royaumes". Encapsule principalement les composants de la logique métier d'authentification et d'autorisation. (Domaine système ou domaine personnalisé)
- Sujet de vérification du sujet, individu, application, application
Le processus de certification du cadre shiro
Authentification des utilisateurs Shiro
Étapes de mise en œuvre du programme d'entrée
- Importer la bibliothèque de pots de Shiro
- Ajouter le fichier de configuration shiro * .ini
syntaxe:
- [users] définit la liste des utilisateurs
- [main] la "racine" du conteneur correspondant au fichier de configuration ini, qui est équivalent à applicationContext.xml - Code de test
@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());
}
Résultat:
Erreur de compte: org.apache.shiro.authc.UnknownAccountException
Erreur de mot de passe: org.apache.shiro.authc.IncorrectCredentialsException
- Royaume personnalisé
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;
}
}
Gestion des permissions de Shiro
1. L'ID d'autorisation requis par l'URI de la demande doit être spécifié dans le fichier de configuration
<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. Autoriser les utilisateurs dans le royaume personnalisé
//权限授予
@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;
}
Application intégrée de shiro et ssm
La configuration de base est la suivante:
- 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 du fichier printemps applicationContext.xml
<!-- 开启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>
Esquisse du processus d'authentification des utilisateurs: