Core Class Introduction Authentication
Authentication is an interface, used to represent the user authentication information, before the user login authentication information will be encapsulated as a authentication concrete implementation of the class object, after the successful login authentication will generate a more comprehensive information, including user rights and other information The authentication object is then saved in the SecurityContext held by Securitycontextholder for subsequent programs, such as authentication of access rights.
Securitycontextholder
Securitycontextholder is used to save the securitycontext. The SecurityContext contains detailed information about the user who is currently accessing the system. By default, Securitycontextholder will use ThreadLocal to save the SecurityContext, which means that in a method in the same thread we can get the current SecurityContext. Because of the thread pool, it would be safer for us to store the SecurityContext in ThreadLocal if we were to clear the ThreadLocal every time after the request was completed. These jobs Spring Security has done for us automatically, that is, the ThreadLocal of the current thread will be cleared at the end of each request.
A series of static methods are defined in Securitycontextholder, and the internal logic of these static methods is basically implemented by the Securitycontextholderstrategy held by Securitycontextholder. such as GetContext (), SetContext (), Clearcontext (), etc. The default use of strategy is based on the ThreadLocal threadlocalsecuritycontextholderstrategy. In addition, Spring Security provides two types of strategy implementations, Globalsecuritycontextholderstrategy and Inheritablethreadlocalsecuritycontextholderstrategy, the former represents the global use of the same securitycontext, such as C/s structure of the client; the latter uses Inheritablethreadlocal to store SecurityContext, that is, the child thread can use the variables stored in the parent thread.
In general, we can use the default strategy, but if we want to change the default strategy,spring Security gives us two methods, both of which are implemented by changing the strategyname. In Securitycontextholder, three different types of strategy are named Mode_threadlocal, Mode_inheritablethreadlocal, and Mode_global respectively. The first is to specify the strategy that needs to be used by Securitycontextholder's static Method Setstrategyname (), and the second way is specified by System properties, where the property name defaults to " Spring.security.strategy ", the property value is the name of the corresponding strategy.
Spring Security uses a authentication object to describe information about the current user. Securitycontextholder holds the current user's securitycontext, and SecurityContext holds a reference to the authentication that represents the current user's information. This authentication object does not need to be created by ourselves, and in the process of interacting with the system, Spring Security automatically creates the corresponding authentication object for us and assigns it to the current securitycontext. But often we need to get information about the current user in the program, such as the most common is to get the user name of the currently logged in user. Anywhere in the program, we can get the user name of the current user by the following way.
Public String Getcurrentusername () { = securitycontextholder.getcontext (). Getauthentication (). Getprincipal (); if instanceof userdetails) { return ((userdetails) principal). GetUserName (); } if instanceof Principal) { return ((Principal) Principal). GetName (); } return string.valueof (principal); }
The Authentication.getprincipal () can be used to obtain information that represents the current user, which is typically an instance of userdetails. Getting the user name of the current user is a more common requirement, as the above code is actually implemented for us in the implementation class in authentication, so the simplest way to get the user name of the current user is as follows.
Public String Getcurrentusername () { return securitycontextholder.getcontext (). Getauthentication (). GetName (); }
Also, if the corresponding securitycontext does not exist when calling Securitycontextholder.getcontext () to get SecurityContext, Spring Security will create an empty The SecurityContext and returns.
AuthenticationManager and Authenticationprovider
AuthenticationManager is an interface for processing authentication (authentication) requests. In which only one method authenticate () is defined, and the method receives only one authentication object representing the authentication request as a parameter, and if the authentication succeeds, it returns a authentication object that encapsulates information such as the current user's rights.
throws Authenticationexception;
In Spring Security, the default implementation of AuthenticationManager is Providermanager, and it does not process the authentication request directly, but instead delegates to its configured Authenticationprovider list. Each authenticationprovider is then used in turn for authentication, and if a authenticationprovider-certified result is not NULL, the Authenticationprovider has been successfully certified, Subsequent authenticationprovider will no longer continue to be certified. Then directly with the Authenticationprovider certification results as the Providermanager certification results. If all of the Authenticationprovider's authentication results are null, then the authentication fails, and a providernotfoundexception is thrown. The most common way to verify authentication requests is to load the corresponding userdetails according to the requested user name, and then match the password of the userdetails with the password of the authentication request, consistent with the authentication pass. The Daoauthenticationprovider inside Spring Security is the way it is used. The internal use of Userdetailsservice is responsible for loading the userdetails,userdetailsservice will be explained in the next section. After the authentication succeeds, the loaded userdetails is used to encapsulate the authentication object to be returned, and the loaded Userdetails object contains information such as user permissions. Authentication objects that are successfully returned by authentication will be saved in the current securitycontext.
When we use NameSpace, the use of the Authentication-manager element causes Spring Security to create a providermanager internally, which can then be The Authentication-provider element adds authenticationprovider to it. When defining a authentication-provider element, if no association is specified through the ref attribute which authenticationprovider,spring Security is used by default Daoauthenticationprovider. After using NameSpace, we will not declare Providermanager again.
<alias= "AuthenticationManager"> <Security: Authentication-provider user-service-ref= "Userdetailsservice"/> </security:authentication-manager>
If we do not use NameSpace, then we should declare a providermanager in the ApplicationContext.
Clear voucher after successful authentication
By default, Providermanager clears the credential information in the returned authentication, such as a password, after the authentication is successful. So if you cache the returned authentication information in a stateless application, then you will fail to use the cached information again, because it does not already have credentials such as passwords. So you should take this into account when using the cache. One workaround is to set the Erasecredentialsafterauthentication property of Providermanager to False, or to cache the credential information together when caching.
Userdetailsservice
The return type through Authentication.getprincipal () is Object, but in many cases it is actually a userdetails instance. Userdetails is a core interface in Spring Security. It defines a number of methods that can be used to obtain authentication-related information such as user names, passwords, permissions, and so on. Most of the Userdetails implementation classes used within Spring Security are built-in User classes, which we can use directly if we want to use userdetails. In many parts of Spring Security, the use of user information is mostly userdetails, such as when logging in to authentication. When signing up for certification, Spring Security will obtain the corresponding userdetails through the Userdetailsservice loaduserbyusername () method, and the userdetails will be assigned to the authentication Pass Authentication principal, and then deposit the authentication into the SecurityContext. After that, if you need to use user information, you get the principal of authentication stored in SecurityContext by Securitycontextholder.
Usually we need to get other information about the current user in the app, such as Email, phone, etc. The Userdetails object that is stored in authentication principal only contains information about the authentication may not meet our requirements. At this point we can implement our own userdetails, in which we can define some ways to get the user's other information, so that in the future we can directly from the current SecurityContext authentication Principal To obtain this information in the As mentioned above, Userdetails is loaded through the Userdetailsservice Loaduserbyusername () method. Userdetailsservice is also an interface, and we also need to implement our own userdetailsservice to load our custom userdetails information. Then assign it to the Authenticationprovider. Here is an example of configuring Userdetailsservice.
<!--AuthenticationManager for Certification - <Security:authentication-manageralias= "AuthenticationManager"> <Security:authentication-providerUser-service-ref= "Userdetailsservice" /> </Security:authentication-manager> <BeanID= "Userdetailsservice"class= "Org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl"> < Propertyname= "DataSource"ref= "DataSource" /> </Bean>
The Jdbcdaoimpl we use in the code above is the implementation of the userdetailsservice provided by spring security, and spring security provides us with userdetailsservice another real Now, Inmemorydaoimpl.
Its role is to load userdetails information from the database. The default scripts that load related information are already defined, and they can also be specified by the relevant properties of the Jdbcdaoimpl. About the use of Jdbcdaoimpl will be in the explanation of Authenticationprovider time to do a relatively detailed introduction.
Jdbcdaoimpl
Jdbcdaoimpl allows us to load userdetails from the database, which uses the Spring JdbcTemplate to operate, so we need to specify a data source for it. In addition, we need to specify the SQL statement that queries the user information through username through the Usersbyusernamequery property, and the Authoritiesbyusernamequery property to specify the S for which the user's permissions are queried by username QL statement; If we enable support for user group permissions by setting Jdbcdaoimpl enablegroups to True, then we also need to specify the Groupauthoritiesbyusernamequery property by using the username query SQL statement for the user group permissions. When none of this information is specified, the default SQL statement is used, and the default SQL statement is as follows.
SelectUsername, password, enabled fromUserswhereUsername=?--query user information according to usernameSelectUsername, authority fromAuthoritieswhereUsername=?--Querying user rights information according to usernameSelectG.id, G.group_name, ga.authority fromGroups G, Groups_members GM, Groups_authorities GAwhereGm.username=? andG.id=ga.group_id andG.id=gm.group_id--querying user group permissions based on username
Querying with the default SQL statement means that we should have a corresponding table and table structure in our corresponding database, and the default table created by Spring Security provides us with the following script.
Create TableUsers (username varchar_ignorecase ( -) not NULL Primary Key, password varchar_ignorecase ( -) not NULL, Enabled Boolean not NULL);Create TableAuthorities (username varchar_ignorecase ( -) not NULL, authority Varchar_ignorecase ( -) not NULL, constraintFk_authorities_usersForeign Key(username)Referencesusers (username)); Create Unique IndexIx_auth_username onauthorities (username,authority);Create Tablegroups (IDbigintGenerated by default as Identity(Start with 0)Primary Key, Group_name varchar_ignorecase ( -) notnull);Create Tablegroup_authorities (group_idbigintNotnull, Authorityvarchar( -) Notnull,constraintFk_group_authorities_groupForeign Key(group_id)Referencesgroups (ID));Create Tablegroup_members (IDbigintGenerated by default as Identity(Start with 0)Primary Key, usernamevarchar( -) Notnull, group_idbigintNotnull,constraintFk_group_members_groupForeign Key(group_id)ReferencesGroups (ID));
In addition, when using the Jdbc-user-service element, the Jdbcdaoimpl is used by default on the underlying Spring Security.
<Security:authentication-manageralias= "AuthenticationManager"> <Security:authentication-provider> <!--the implementation of Userdetailsservice based on JDBC, Jdbcdaoimpl - <Security:jdbc-user-serviceData-source-ref= "DataSource"/> </Security:authentication-provider> </Security:authentication-manager>
Inmemorydaoimpl
Inmemorydaoimpl is mainly for testing purposes, it simply saves the user information in memory. When using NameSpace, the userdetailsservice used with the User-service element Spring Security is Inmemorydaoimpl. At this point, we can simply use the user element to define a userdetails.
< Security:user-service > < name= "user" password= "user" authorities= "Role_ USER "/> </security:user-service>
The above configuration indicates that we have defined a user username whose corresponding password is user and has Role_user permissions. In addition, User-service supports the use of the properties file to specify user information, such as:
<properties= "/web-inf/config/users.properties"/>
Where the properties file should follow the following format:
Username=password,grantedauthority[,grantedauthority][,enabled|disabled]
So, corresponding to the above configuration file, the contents of our Users.properties file should look like this:
#username =password,grantedauthority[,grantedauthority][,enabled| Disabled]user=user,role_user
Grantedauthority
Authentication Getauthorities () can return the permissions that the current authentication object has, that is, the permissions that the current user has. The return value is an array of type grantedauthority, and each Grantedauthority object represents a permission given to the current user. Grantedauthority is an interface that is usually loaded by userdetailsservice and then given to Userdetails.
Only one getauthority () method is defined in Grantedauthority, which returns a string representing the string representation of the corresponding permission and should return NULL if the corresponding permission cannot be represented by a string.
Spring Security has a simple implementation simplegrantedauthority for grantedauthority. The class simply receives a string that represents the permission. All authenticationprovider within Spring Security use Simplegrantedauthority to encapsulate authentication objects.
Spring Security Core Class