Heim >Java >javaLernprogramm >Wie SpringBoot Shiro integriert, um die Berechtigungskontrolle zu implementieren
Apache Shiro ist ein leistungsstarkes und benutzerfreundliches Java-Sicherheitsframework, das Authentifizierung, Autorisierung, Passwort und Sitzungsverwaltung durchführt. 1.1 Einführung in Shiro Das Konzept stellt alles dar, was mit dem aktuellen Programm interagiert, z. B. Crawler, Skripte usw. Alle Subjekte sind an den SecurityManager gebunden und alle Interaktionen mit dem Subjekt werden an den SecurityManager delegiert; der Subjekt kann als Fassade betrachtet werden, der SecurityManager ist der eigentliche Ausführende.
SecurityManager: Dies ist der Kern des Shiro-Frameworks. Alle sicherheitsrelevanten Vorgänge werden damit interagieren.
Realms: Fungiert als „Brücke“ zwischen Shiro und Anwendungssicherheitsdaten. Bei der Authentifizierung (Anmeldung) und Autorisierungsüberprüfung (Zugriffskontrolle) für einen Benutzer muss SecurityManager den entsprechenden Benutzer zum Vergleich von Realm abrufen, um die Daten zu ermitteln Ist die Identität des Benutzers legal? Es ist auch erforderlich, die entsprechende Rolle/Berechtigung des Benutzers von Realm zu erhalten, um zu überprüfen, ob der Benutzer den Vorgang ausführen kann.
1.2, spezifische Implementierung des Codes
<!--shiro--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.7.1</version> </dependency> <!--shiro整合thymeleaf--> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency> <!--shiro缓存--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.7.1</version> </dependency>
shiro wird standardmäßig mit JSP verwendet, und hier sind alle JAR-Pakete, die importiert werden müssen, um Thymeleaf mit Shiro zu integrieren
Im Allgemeinen muss die Integration nur die Implementierung von zwei Klassen abschließen
Eine ist ShiroConfig und die andere ist CustomerRealm
Wenn Sie Shiro hinzufügen müssen Cache und es ist kein integrierter Cache. Aber der Redis-Cache muss auch zwei andere Klassen schreiben
Eine ist RedisCache und die andere ist RedisCacheManager
1.2.3, Projektstruktur
package com.yuwen.config; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; import com.yuwen.shiro.cache.RedisCacheManager; import com.yuwen.shiro.realm.CustomerRealm; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.realm.Realm; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.HashMap; import java.util.Map; @Configuration public class ShiroConfig { //让页面shiro标签生效 @Bean public ShiroDialect shiroDialect(){ return new ShiroDialect(); } //1、创建shiroFilter 负责拦截所有请求 @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean(); //给filter设置安全管理 factoryBean.setSecurityManager(defaultWebSecurityManager); //配置系统的受限资源 //配置系统公共资源 全部都能访问的设置anon Map<String,String> map = new HashMap<>(); map.put("/main","authc");//请求这个资源需要认证和授权 authc表示需要认证后才能访问 map.put("/admin","roles[admin]"); //表示admin角色才能访问 roles[]表示需要什么角色才能访问 map.put("/manage","perms[user:*:*]"); //表示需要user:*:*权限才能访问 perms[]表示需要什么权限才能访问 //访问需要认证的页面如果未登录会跳转到/login路由进行登陆 factoryBean.setLoginUrl("/login"); //访问未授权页面会自动跳转到/unAuth路由 factoryBean.setUnauthorizedUrl("/unAuth"); factoryBean.setFilterChainDefinitionMap(map); return factoryBean; } //2、创建安全管理器 @Bean public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("getRealm") Realm realm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //给安全管理器设置 securityManager.setRealm(realm); return securityManager; } //3、创建自定义的realm @Bean public Realm getRealm(){ CustomerRealm customerRealm = new CustomerRealm(); //修改凭证校验匹配器 HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); //设置加密算法为md5 credentialsMatcher.setHashAlgorithmName("MD5"); //设置散列次数 credentialsMatcher.setHashIterations(1024); customerRealm.setCredentialsMatcher(credentialsMatcher); return customerRealm; } }Da es im Allgemeinen nicht sicher ist, Klartext-Passwörter in der Datenbank festzulegen, habe ich das Passwort hier mit MD5 verschlüsselt. Meine Verschlüsselungsmethode ist: Passwort = Passwort + Salt + Anzahl von Hashes und dann MD5-Verschlüsselung, also erstellen Sie hier eine benutzerdefinierte. Realm muss einen Matcher festlegen, damit das Passwort beim Anmelden erfolgreich abgeglichen werden kann
1.2.5, die Implementierung von CustomerRealm
package com.yuwen.shiro.realm; import com.yuwen.pojo.User; import com.yuwen.pojo.vo.ViewPerms; import com.yuwen.pojo.vo.ViewRole; import com.yuwen.service.UserService; import com.yuwen.shiro.salt.MyByteSource; 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.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.CollectionUtils; import org.springframework.util.ObjectUtils; import javax.annotation.Resource; import java.util.List; //自定义realm public class CustomerRealm extends AuthorizingRealm { @Resource private UserService userService; //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //获取身份信息 String primaryPrincipal = (String)principalCollection.getPrimaryPrincipal(); //根据主身份信息获取角色 和 权限信息 List<ViewRole> roles = userService.findRolesByUsername(primaryPrincipal); if (!CollectionUtils.isEmpty(roles)){ SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); roles.forEach(viewRole -> { simpleAuthorizationInfo.addRole(viewRole.getName()); //权限信息 List<ViewPerms> perms = userService.findPermsByRoleId(viewRole.getName()); if (!CollectionUtils.isEmpty(perms)){ perms.forEach(viewPerms -> { simpleAuthorizationInfo.addStringPermission(viewPerms.getPName()); }); } }); return simpleAuthorizationInfo; } return null; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //获取登入的身份信息 String principal = (String) authenticationToken.getPrincipal(); User user = userService.findByUsername(principal); if (!ObjectUtils.isEmpty(user)){ //ByteSource.Util.bytes(user.getSalt()) 通过这个工具将盐传入 //如果身份认证验证成功,返回一个AuthenticationInfo实现; return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),new MyByteSource(user.getSalt()),this.getName()); } return null; } }
Diese Authentifizierung wird beim Anmelden automatisch aufgerufen in. Wenn während der Überprüfung ein Fehler auftritt, wird eine Ausnahme in der Controller-Schicht gemeldet. Ich habe die Ausnahme erhalten und behandelt. Ausnahmebehandlung während der Anmeldung in der Controller-Schicht. 1.2.6, Shiro-Cache-Konfiguration Nachdem sich der Benutzer angemeldet hat, müssen seine Benutzerinformationen und Rollen/Berechtigungen nicht jedes Mal überprüft werden. Dies kann die Effizienz verbessern
@PostMapping("/login") public String login(String username,String password){ //获取主体对象 Subject subject = SecurityUtils.getSubject(); try { //自动调用CustomerRealm 类中的身份验证方法 subject.login(new UsernamePasswordToken(username,password)); return "index"; }catch (UnknownAccountException e){ //接收异常并处理 e.printStackTrace(); model.addAttribute("msg","用户名有误,请重新登录"); }catch (IncorrectCredentialsException e){//接收异常并处理 e.printStackTrace(); model.addAttribute("msg","密码有误,请重新登录"); } return "login"; }Der mit reids integrierte Cache wird hier nicht erklärt. Der Quellcode ist unten aufgeführt Authentifizierung erforderlich oder auf welche Rollen oder Berechtigungen zugegriffen werden kann
@Bean public Realm getRealm(){ CustomerRealm customerRealm = new CustomerRealm(); //开启缓存管理 customerRealm.setCacheManager(new EhCacheManager()); //开启全局缓存 customerRealm.setCachingEnabled(true); //开启认证缓存 customerRealm.setAuthenticationCachingEnabled(true); customerRealm.setAuthenticationCacheName("authenticationCache"); //开启权限缓存 customerRealm.setAuthorizationCachingEnabled(true); customerRealm.setAuthorizationCacheName("authorizationCache"); return customerRealm; }1.3, einfacher Test
1.3.1, Administratorrolle Alle Berechtigungen testen
1.3.2, kein Rollen- und Berechtigungstest1.3.3, keine Rolle und kein Berechtigungstest
Das obige ist der detaillierte Inhalt vonWie SpringBoot Shiro integriert, um die Berechtigungskontrolle zu implementieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!