This is the fifth day of my participation in the August More text Challenge. For details, see:August is more challenging
Overview of Shiro
1.1 Rights management
1.1.1 Rights Management
Basically, all systems involving user participation should carry out permission management. Permission management belongs to the category of system security. Permission management realizes the control of users’ access to the system, and controls users’ access to and only the authorized resources according to security rules or security policies.
Rights management includes user identity authentication and authorization (authentication and authorization for short). A resource user that needs access control is authenticated. After passing the authentication, the user has the permission to access the resource.
1.1.2 Identity authentication
Identity authentication is the process of judging whether a user is a legitimate user. In the most common simple identity authentication mode, the system checks whether the user name and password entered by a user are consistent with the user name and password stored in the system to determine the user identity. For systems such as fingerprint, show the fingerprint; For a card swiping system such as a hardware Key, a card swiping is required.
1.1.3, authorization,
Authorization, or access control, controls who can access what resources. After identity authentication, the principal can access system resources only after being assigned permission. If the principal does not have permission to access some resources, he cannot access them
2.1 What is Shiro
Apache Shiro ™is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, Session Management. With Shiro’s easy-to-Understand API, You can quickly and easily secure any application — from the smallest mobile applications to the largest web and enterprise applications.
Apache Shiro is a security framework for Java. Shiro makes it very easy to develop applications that are good enough to be used not only in the Java ase environment but also in the JavaEE environment. Shiro can help with authentication, authorization, encryption, session management, integration with the Web, caching, and more.
2.2. Why learn Shiro
- Since Shiro extracts functions related to security authentication into a framework, shiro can quickly complete the development of functions such as authentication and authorization and reduce the system cost.
- Shiro is widely used. Shiro can run in Web applications, non-Web applications, clustered and distributed applications. More and more users are using Shiro.
Spring Security (formerly Acegi) is also an open source permission management framework in the Java domain, but Spring Security runs on Spring, while Shiro is relatively independent, mainly because Shiro is simple and flexible to use. So now more and more users are choosing Shiro.
2.3 basic functions
- Authentication
Identity authentication/login, verifying that the user has the appropriate identity;
- Authorization
Authorization, that is, permission authentication, to verify whether an authenticated user has a certain permission. That is, to determine whether a user can do something, for example, to verify whether a user has a role. Or fine-grained verification of whether a user has a certain permission on a resource;
- SessionManager
Session management, that is, after the user login is a session, before the exit, all its information is in the session; The session can be in a normal JavaSE environment or in a Web environment.
- Cryptography
Encryption, to protect the security of data, such as password encryption stored in the database, rather than plain text storage;
- WebSupport
Web support for easy integration into the Web environment;
- Caching
Cache. For example, after a user logs in, the user information and roles/permissions are not checked every time. This improves efficiency.
- Concurrency
Shiro supports concurrent validation of multi-threaded applications. If you start another thread in one thread, permissions are automatically propagated.
- Testing
Provide test support;
- Run As
Allowing a user to pretend to be another user (if they allow it);
- Remember Me
Remember me, this is a very common feature, that once you log in, you don’t have to log in the next time.
Note: Shiro does not maintain users or privileges; These need to be designed/provided by us; Then inject it into Shiro through the corresponding interface. About the design, the SSM integration in the back of Shiro to say oh
2.4. Architecture Description
- Subject
Subject is the Subject. External applications interact with Subject. Subject records the current operating user and understands the concept of user as the Subject of the current operation, which may be a user requesting through a browser or a running program. A Subject is an interface in Shiro that defines a number of methods related to authentication and authorization. External programs are authenticated by a Subject, which is authenticated and authorized by a SecurityManager
- SecurityManager
The SecurityManager is the core of Shiro and is responsible for the security management of all subjects. The Authentication and authorization of a Subject can be completed through the SecurityManager. Essentially, the SecurityManager implements authentication through the Authenticator, authorization through the Authorizer, and session management through the SessionManager.
SecurityManager is an interface that inherits from the Authenticator, Authorizer, and SessionManager interfaces.
- Authenticator
Authenticator certifier, namely the user identity authentication, the Authenticator is an interface, shiro provides ModularRealmAuthenticator implementation class, Through ModularRealmAuthenticator basically can satisfy most requirements, also can custom authentication.
- Authorizer
Authorizer: The user is authenticated by the Authorizer. When accessing the function, the user needs to check whether the user has the operation permission of the function through the Authorizer.
- Realm
A Realm is the equivalent of a datasource source. A Realm is used by the securityManager to obtain access to user permissions for security purposes. For example, if the user’s identity data is in a database, the Realm needs to obtain the user’s identity information from the database.
** Note: Don’t think of a realm as simply fetching data from a data source. There is also code for authentication, authorization, and validation within a realm. 支那
- sessionManager
SessionManager is session management. The Shiro framework defines a set of session management that does not depend on sessions in a Web container, so Shiro can be used for non-Web applications, or to manage sessions in a single point for distributed applications. This feature enables it to implement single sign-on.
- SessionDAO
The SessionDAO is a set of interfaces for session operations. For example, to store a session to a database, you can use JDBC to store the session to the database.
- CacheManager
CacheManager stores user permission data in the cache to improve performance.
- Cryptography
Shiro provides a suite of encryption/decryption components for easy development. For example, provide common hash, encryption/decryption and other functions.
Download Shiro and Maven dependencies
Shiro.apache.org/download.ht…
- Shro-all is the shiro feature JAR package
- Shro-core is shiro’s basic feature pack
- Shiro – a package for web and Web integration
- Shro-spring integrated package for Shrio and Spring
2. Basic Introduction to Shiro
2.1 Description of shiro. ini file
-
InitializationFile (INI) Initial file. Window Indicates the extension of the system file.
-
Shiro can be used with or without a database connection. If you do not connect to a database, you can configure static data in shiro.ini
2.2 components of the shrio. ini file
[main] : defines a global variable
-
Built-in securityManager object.
-
Write inside [main] when working with a built-in object
[main]SecurityManager. Property = Valuexiaolin=123456SecurityManager. Object property =$xiaolinCopy the code
[users] : Defines the user name and password
[users]
# set username to zhangsan and password to zs
zhangsan=zs
# define user name lisi password lisi with both role1 and role2 roles
lisi=lisi,role1,role2
Copy the code
[Roles] : Defines roles
[roles]
role1= permission name1And permissions2
role2= permissions3And permissions4
Copy the code
[urls] : Defines which built-in urls work. Used in Web applications.
[urls]
#url = built-in filter or custom filter
# Url that appears /login when accessing must be authenticated. The Filter corresponding to authC is supported
/login=authc
No authentication is required for any URL.
/** = anon
All content must ensure that the user is logged in.
/**=user
You must ensure that the user has the role1 and Role2 roles.
/abc= roles [" role1, role2 "]Copy the code
2.3. Detailed explanation of filter
Filter name | The filter class | describe |
---|---|---|
anon | org.apache.shiro.web.filter.authc.AnonymousFilter | Anonymous filter |
authc | org.apache.shiro.web.filter.authc.FormAuthenticationFilter | If you want to continue the operation, you need to perform the corresponding form authentication. Otherwise, the operation fails |
authcBasic | org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter | Basic HTTP authentication filtering, if not, jump to the login page |
logout | org.apache.shiro.web.filter.authc.LogoutFilter | Login logout Filter |
noSessionCreation | org.apache.shiro.web.filter.session.NoSessionCreationFilter | No session created filter |
perms | org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter | Permission filter |
port | org.apache.shiro.web.filter.authz.PortFilter | Port filter, you can set whether to specify the port if not jump to the login page |
rest | org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter | HTTP method filters, which can be specified such as post cannot be accessed |
roles | org.apache.shiro.web.filter.authz.RolesAuthorizationFilter | Role filter to determine whether the current user has specified a role |
ssl | org.apache.shiro.web.filter.authz.SslFilter | The request needs to go through SSL, if not jump back to the login page |
user | org.apache.shiro.web.filter.authc.UserFilter | If you access a known user, like the Remember me function, go through this filter |
Anon: Anonymous processing filter, that is, no login required to access; Generally used for static resource filtering;
Such as: / static / * * = -anon
Authc: Indicates that authentication (login) is required.
Such as: / * * = authc
Roles: Role authorization filter that verifies whether users have resource roles.
Such as: / admin / * = roles/admin
Perms: Permission authorization filter that verifies whether a user has resource permissions.
Such as: / employee/input = perms [” user: the update “]
Logout: Logs out the filter
Such as: / logout = logout
Three, certification
3.1, certification
The authentication process is the user’s identity confirmation process, and the function is the familiar login authentication. The user enters the account and password and submits it to the background, and the background checks the correctness of the account and password by accessing the database.
3.2 Key objects in authentication
3.2.1,Subject: the Subject
The user who accesses the system can be a user or a program. Those who are authenticated are called bodies.
3.2.2,Principal: identity information
The id must be unique, such as the user name, mobile phone number, and email address. A Principal can have multiple identities, but it must have a Primary Principal.
3.2.3,Credential: Credential information
Is security information, such as passwords and certificates, known only to the principal.
3.3 Certification process
The final user comparison is performed by the doGetAuthenticationInfo method in the SimpleAccountRealm class, which validates the user name.
The final password verification is done in the assertCredentialsMatch method of the AuthenticatingRealm class and is automatic. We do not need to do it manually.
3.4 Code implementation
3.4.1 Importing dependencies
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
<scope>provided</scope>
</dependency>
Copy the code
3.4.2 Writing ini files
[users]
xiaolin=Awesome!
zs=13
Copy the code
3.4.3 Writing test classes
/** * to test Shiro foundation */
@Test
public void testShiroBase(a){
// Create Shiro security Manager, which is the core of Shiro
DefaultSecurityManager securityManager = new DefaultSecurityManager();
// Load the ini configuration file to get the user information configured in the configuration file
IniRealm iniRealm = new IniRealm("classpath:shiro-authc.ini");
// Inject a realm object into the securityManager
securityManager.setRealm(iniRealm);
// Inject the security manager into the current environment
SecurityUtils.setSecurityManager(securityManager);
// Get the Subject principal object, whether logged in or not
Subject subject = SecurityUtils.getSubject();
// Print the authentication status
System.out.println("Authentication status"+subject.isAuthenticated());
// Create a token that carries the account number and password
UsernamePasswordToken token = new UsernamePasswordToken("xiaolin"."666");
// Call subject to pass in the token for login
subject.login(token);
System.out.println("Authentication status"+subject.isAuthenticated());
}
Copy the code
3.4.4, pay attention to
If the entered identity and credentials match those configured in the INI file, the login succeeds and the login status is true; otherwise, the login status is false.
There are several conditions for a login failure (exceptions thrown) :
- Account error:
org.apache.shiro.authc.UnknownAccountException
- Password error:
org.apache.shiro.authc.IncorrectCredentialsException
3.4.5 Shiro certification source code analysis
1. Call the Subject. login method for login, which will automatically delegate to the securityManager.login method for login; 2. The securityManager authenticates with the Authenticator; 3, the realization of the Authenticator class invokes ModularRealmAuthenticator realm from the ini configuration file user account and password, true is used here IniRealm (shiro bring, equivalent to a data source); 4, IniRealm first find the account according to the account of the token to the ini, if can’t find to ModularRealmAuthenticator returns null, if find the matching password, matching password authentication by success.
3.5 custom Realm
Custom realms are used a lot in real world development, and the account information we need to use usually comes from the application or database, rather than the configuration of the INI file we used earlier.
Call the doGetAuthenticationInfo method in the AuthenticatingRealm. If the returned info is not null, the account exists and the password verification is performed. If it doesn’t, it throws the UnknownAccountException.
So, if we want to customize the Realm, we should override the doGetAuthenticationInfo() method and implement the account verification in the method. And return the AuthenticationInfo object to the upper-level caller AuthenticatingRealm for further verification.
Realm provided by Shiro
3.5.2, SimpleAccountRealm
When we Debug, we can see that SimpleAccountRealm is used in the source code for authentication.
3.5.3, SimpleAccountRealm part of the source code
/ / certification
public class SimpleAccountRealm extends AuthorizingRealm {
/ /... omit
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
SimpleAccount account = getUser(upToken.getUsername());
if(account ! =null) {
if (account.isLocked()) {
throw new LockedAccountException("Account [" + account + "] is locked.");
}
if (account.isCredentialsExpired()) {
String msg = "The credentials for account [" + account + "] are expired";
throw newExpiredCredentialsException(msg); }}return account;
}
/ / authorization
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = getUsername(principals);
USERS_LOCK.readLock().lock();
try {
return this.users.get(username);
} finally{ USERS_LOCK.readLock().unlock(); }}}Copy the code
3.6 SSM integrated Shiro certification
3.6.1. Adding dependencies
<properties>
<shiro.version>1.5.2</shiro.version>
</properties>
<! - shiro core -- -- >
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<! -- Shiro Web module -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<! -- Shiro and Spring integration -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<! -- EhCache cache used by Shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
<! -- Shiro dependent log package -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<! Freemarker's Shiro tag library -->
<dependency>
<groupId>net.mingsoft</groupId>
<artifactId>shiro-freemarker-tags</artifactId>
<version>1.0.1</version>
</dependency>
Copy the code
3.6.2. Configure proxy Filters
When accessing, a series of pre-processing operations are required. Shiro chooses to use a filter to intercept this, because Shiro does not rely on the Spring container, so the absence of SpringMVC means that interceptors cannot be used, but filters are different and can be used for any Web project. We need to configure the filters in web.xml.
<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>
Copy the code
DelegatingFilterProxy here USES a proxy filter, because the real shiroFilter need to inject a lot of complex objects, and the web. Only configuration in XML string or a number of parameters, can’t meet, Therefore, we will leave the shiroFilter to Spring to manage and configure through Spring’s XML file. After the DelegatingFilterProxy filter is used, the DelegatingFilterProxy filter automatically finds the beans with the same name as the filter-name configured in the Spring container after the browser sends the request and the request is intercepted by the proxy filter.
3.6.3 create shiro.xml
<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">
<! -- custom Realm-->
<bean id="myRealm" class="cn.linstudy.shiro.CarBusinessRealm"/>
<! -- Create a security manager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean>
<bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<! -- Reference the specified security manager -->
<property name="securityManager" ref="securityManager"/>
<! -- Shiro's default login address is /login.jsp. Now specify our own login page address -->
<property name="loginUrl" value="/login.html"/>
<! -- Path rule -->
<property name="filterChainDefinitions">
<! -- Configure the request interception mode, can be anonymous or -->
<value>
/empLogin=anon
/static/**=anon
/upload/**=anon
/getImage=anon
/getEmailCode=anon
/checkEmail=anon
/checkUsername=anon
/error=anon
/fronted/**=anon
/**=authc
</value>
</property>
</bean>
</beans>
Copy the code
3.6.4. Import shrio.xml
Introduce Shiro.xml in MVC.xml
<import resource="classpath:shiro.xml"/>
Copy the code
3.6.5. Configure security Manager
We need to configure the security manager in Shiro.xml.
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"></bean>
Copy the code
3.6.6 configuring custom realms
public class CarBusinessRealm extends AuthorizingRealm {
@Autowired
private EmployeeService employeeService;
/ / certification
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException {
// Obtain the username from the token (when the user logs in)
String username = (String) token.getPrincipal();
// Check whether the database exists
Employee employee = employeeService.selectByUsername(username);
if(employee ! =null) {
// If the user name is correct, return an identity object
return new SimpleAuthenticationInfo(employee, employee.getPassword(), this.getName());
}
return null; }}Copy the code
3.6.7 configuring custom realms
<bean id="myRealm" class="cn.linstudy.shiro.CarBusinessRealm"/>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean>
Copy the code
3.6.8. Changing the Login Method
try {
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
SecurityUtils.getSubject().login(token);
Employee employee = employeeMapper.selectByUsername(username);
return employee;
} catch (UnknownAccountException e) {
throw new CarBussinessException("Incorrect user name");
} catch (IncorrectCredentialsException e) {
throw new CarBussinessException("Password error");
}
Copy the code
3.7, logout
Shiro has a built-in logout method, so we simply add /logout=logout to shiro’s path rule in shiro. XML.