Shiro
Three major functions of Shiro
Shiro has three core components, namely Subject
, SecurityManager
andRealm
- Subject : for
认证主体
. The object that application code interacts with directly is Subject, which represents the current user. ContainsPrincipals
andCredentials
two messages. - SecurityManager : for
安全管理员
. It is the core of Shiro architecture. All interactions with the Subject will be delegated to the SecurityManager. The Subject is equivalent to a facade, and the SecurityManager is the real executor. It is responsible for interacting with other components of Shiro. - Realm : Yes
一个域
. Acts as a "bridge" between Shiro and application security data. Shiro obtains security data (such as users, roles, permissions) from Realm. That is to say, if SecurityManager wants to verify the user's identity, it needs to obtain the corresponding user from Realm for comparison to determine whether the user's identity is legal; it also needs to obtain it from Realm. The user's corresponding roles and permissions are used to verify whether the user's operation can be carried out. Realm can be regarded as a DataSource, that is, a secure data source.
- Authentication : Identity authentication, login, verifying whether the user has the corresponding identity;
- Authorization : authorization, that is, authority verification, to verify whether an authenticated user has a certain authority, that is, to determine whether the user can perform any operations, such as verifying whether a user has a certain role, or fine-grained verification of a user Do you have certain permissions on a certain resource?
- Session Manager : Session management, that is, after the user logs in, it is the first session. Before exiting, all its information is in the session; the session can be an ordinary JavaSE environment or a Web environment;
- Cryptography : Encryption to protect the security of data, such as passwords being encrypted and stored in the database instead of being stored in clear text;
- Web Support : Web support, which can be easily integrated into the Web environment;
- Caching : Caching, for example, after a user logs in, his user information, roles, and permissions do not need to be checked every time, which can improve efficiency.
- Concurrency : Shiro supports concurrent verification of multi-threaded applications, that is, if you start another thread in one thread, the permissions can be automatically propagated to it.
- Testing : Provide testing support;
- RunAs : Allows one user to pretend to be another user (if they allow it);
- Remember Me : Remember me, this is a very common function, that is, after logging in once, you don’t need to log in next time.
Shiro architecture (external)
Looking at Shiro from the outside, that is, observing how to use shiro to complete work from the perspective of the application: Subject user, SecurityManager manages all user Realm connection data
- subject : The object that the application code directly interacts with is Subject. In other words,
Shiro
the core of the external API isSubject
that Subject represents the current user. This user is not necessarily a specific person. Anything that interacts with the current application is Subject, such as the network. All interactions with crawlers, robots, etc. with Subject will be delegated to SecurityManager; Subject is actually a facade, and SecurityManageer is the actual executor. - SecurityManager : Security manager, that is, all security-related operations will
SercurityManager
interact with it, and it manages all Subjects. It can be seen that it is the core of Shiro. It is responsible for interacting with other components of Shiro. It is equivalent to SpringMVC's DispatcherServlet character of - Realm : Shiro obtains security data (such as users, roles, permissions) from Realm. That is to say, if SecurityManager wants to verify the user's identity, it needs to obtain the corresponding user from Realm for comparison to determine whether the user's identity is legal; it also needs to obtain the user from Realm
Realm
. Corresponding roles and permissions are used to verify whether the user's operation can be carried out. You can view Realm as DataSource;
Shiro architecture (internal)
- Subject : Any user who can interact with the application;
- Security Manager : Equivalent to SpringMVC
DispatcherSerlet
; it is Shiro心脏
. All specific interactionsSecurity Manager
are controlled through it. It manages all Subjects and is responsible for authentication, authorization, session, and cache management. - Authenticator : Responsible for
Subject
authentication, it is an extension point that can be customized; it can be used认证策略
(Authentication Strategy), that is, under what circumstances is the user authentication passed? - Authorizer : Authorizer, that is, access controller, used to determine whether the subject has permission to perform corresponding operations; that is, it controls which functions in the application the user can access;
- Realm : There can be one or more realms, which can be considered as a secure entity data source, that is, used to obtain secure entities. It can be implemented using JDBC, or it can be implemented in memory, etc., and is provided by the user; therefore, it is generally Every application needs to implement its own realm
- SessionManager : A component that manages the Session life cycle. Shiro can not only be used in the Web environment, but also in the ordinary JavaSE environment.
- CacheManager : Cache controller to manage caches such as users, roles, permissions, etc. Because these data rarely change, placing them in the cache can improve access performance;
- Cryptography : cryptography module, Shiro improves some common encryption components for password encryption, decryption, etc.
shiro certification process
shiro authorization process
Shiro uses
SaaSExport practice project usage (ssm)
pom.xml dependencies
xml
Copy code
<!--Shiro和Spring整合--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency> <!--Shiro核心包--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.3.2</version> </dependency>
web.xml
xml
Copy code
<!--服务器启动时加载Spring配置文件--> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:spring.xml classpath:shiro.xml </param-value> </context-param> <!--Shiro核心过滤器--> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
shiro.xml
xml
Copy code
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--id=shiroFilter不能写错,大小写敏感,这个id的值与filter的名字相同--> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="defaultWebSecurityManager"/> <!--**表示当前路径下所有资源,包括一级目录,二级目录,等等--> <!--anon放在最前面,authc放在最后面--> <property name="filterChainDefinitions"> <value> /css/** = anon /img/** = anon /make/** = anon /plugins/** = anon /login.do = anon /system/dept/list.do = perms["部门管理"] /system/user/list.do = perms["用户管理"] /system/company/list.do = perms["企业管理"] /system/module/list.do = perms["模块管理"] /system/role/list.do = perms["角色管理"] /system/syslog/list.do = perms["日记管理"] /** = authc </value> </property> <property name="unauthorizedUrl" value="/unauthorized.jsp"/> </bean> <bean id="defaultWebSecurityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="authReaml"/> </bean> <bean id="authReaml" class="com.it.shiro.AuthReaml"> <!-- <!–将123456转成MD5格式的密码,然后再和数据库中的MD5密码进行比较–>--> <!-- <!–所以在企业开发中,配置方式很常用,可拔插–>--> <!-- <property name="credentialsMatcher" ref="hashedCredentialsMatcher"/>--> </bean> <!--我们使用MD5加密器--> <!-- <bean id="hashedCredentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">--> <!-- <property name="hashAlgorithmName" value="MD5"/>--> <!-- </bean>--> </beans>
Permission parameter table
Implement class AuthReaml
The permissions of this exercise project are based on the RBAC model. The user table, role table, module table and two intermediate tables are used to obtain the corresponding role of the user through the intermediate table of user and role, and then the corresponding permissions are obtained through the intermediate table of role and module. This is also a typical anti-three-paradigm data table design (although I have forgotten which three paradigms are, will there be anyone who strictly abides by the three-paradigm to design data tables?)
java
Copy code
package com.it.shiro; import com.it.model.module.Module; import com.it.model.user.User; import com.it.service.module.ModuleService; import com.it.service.user.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; 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.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; /** * 自定义Shiro认证和权授的业务逻辑 */ public class AuthReaml extends AuthorizingRealm { @Autowired private UserService userService; @Autowired private ModuleService moduleService; /** * 认证 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("认证"); //1. 将AuthenticationToken接口强转成UsernamePasswordToken实现类并从中获取用户输入的用户名(邮箱)和密码 UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; String username = token.getUsername(); String password = new String(token.getPassword());//char[]->java.lang.String //2. 根据用户名(邮箱)去数据库中查询用户是否存在,userDB中有密码 User userDB = userService.findByEmail(username); //3. 如果用户不存在,就返回null if(userDB == null){ System.out.println("用户不存在"); return null; } System.out.println("uid "+userDB.getUserId()); System.out.println("password "+userDB.getPassword()); //4. 如果用户存在,就返回AuthenticationInfo接口的SimpleAuthenticationInfo实现类对象,该对象中封装三个信息: a)认证后的userDB对象 b)认证后的userDB对象封装的数据库密码 c)Realm的别名,可以为"" AuthenticationInfo info = new SimpleAuthenticationInfo(userDB,userDB.getPassword(),""); //Shiro会在后台对userDB.getPassword()数据库密码和password用户填写的密码在内存中对比 return info; } /** * 授权 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("授权"); //1. 使用SecurityUtils获取Subject对象 Subject subject = SecurityUtils.getSubject(); //2. 使用Subject对象获取User对象 User loginUser = (User) subject.getPrincipal(); //3. 根据用户ID查询该用户可以访问的模块,这里的moduleList集合中Module只有模块名name属性 List<Module> moduleList = moduleService.findModuleByUid(loginUser.getUserId()); // List<Module> moduleList = moduleService.findByUserId(loginUser.getId()); //4. 遍历模块集合,将每一个模块的编号或名称封装到 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); for (Module module : moduleList) { //info.addStringPermission("部门管理"); info.addStringPermission(module.getName()); } //SimpleAuthorizationInfo对象中,以便Shiro内容进行授权控制 //5. 返回SimpleAuthorizationInfo对象 return info; } }
call method
scss
Copy code
//1.使用SecurityUtils获取subject对象 Subject subject = SecurityUtils.getSubject(); //2.使用AuthenticationToken接口的UsernamePasswordToken实现类封装用户输入的用户名(邮箱)和密码信息 AuthenticationToken token = new UsernamePasswordToken(username,password); //3.调用subject的login()进行认证,底层调用AuthRealm.doGetAuthenticationInfo()认证方法 subject.login(token); //4. 调用subject的getPrincipal()获取认证后的用户,这个userDB就是数据库的密码 User userDB = (User) subject.getPrincipal(); //5. 将用户放入session中 request.getSession().setAttribute("loginUser",userDB);
SpringBoot usage (excerpted from the Internet)
pom.xml
org.apache.shiro shiro-spring 1.4.1
config configuration
Create a new config package and create ShiroConfig and UserRealm
typescript
Copy code
@Controller public class ShiroConfig { //三大核心要素: //ShiroFilterFactoryBean //第三步: public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); return bean; } //DafaultWebSecurityManager //第二步: @Bean(name="securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //关联UserRealm securityManager.setRealm(userRealm); return securityManager; } //创建realm对象,需要自定义类 //第一步: @Bean public UserRealm userRealm(){ return new UserRealm(); } }
scala
Copy code
public class UserRealm extends AuthorizingRealm { //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了=》授权doGetAuthorizationInfo"); return null; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("执行了=》认证doGetAuthenticationInfo"); return null; } }
Relevant information
SpringBoot integrates shiro