RESTful API permission design – Sureness integration with SpringBoot sample – database scheme
In the previous article RESTful API Percession Design – Quickly Set Up Percession Project, we described in detail step by step the use of Sureness integrated with SpringBoot to set up a permissions project background with complete authentication function from scratch. This quick set up background is based on configuration files. In other words, the user information and resource information and the corresponding permissions information are written in the configuration file instead of the database. However, in the conventional enterprise application background, these data and information are stored in the database. Today, we will describe in detail the use of the database as the data source to integrate Sureness and SpringBoot to build an enterprise-level fully functional authentication background project.
For SURENSS, no matter the configuration file scheme or the database scheme, it just replaces different data sources. We can completely modify and replace the previously built project based on configuration file and replace it with the database as the data source.
Learn about the data loading interface provided by Sureness
First of all, let’s take a look at the two interfaces provided by Sureness for user information and resource permission information. Users can implement these interfaces to provide data to Sureness from different data sources. When we switch the project from configuration file mode to database mode, we simply replace the implementation classes of these interfaces.
PathTreeProvider resource permission configuration information of the data source interface, we can implement from the database, text, etc. Load the interface wants the resource permission configuration data
public interface PathTreeProvider {
Set<String> providePathData();
Set<String> provideExcludedResource();
}
ProvidepathData loads the resource permission configuration information, which is the resourceOLE column of sureness.yml in our configuration file mode. ProvideExcludedResource loads which resources can be filtered without authentication, that is, the ExcludedResource information column under sureness.yml, as follows.
resourceRole:
- /api/v2/host===post===[role2,role3,role4]
- /api/v2/host===get===[role2,role3,role4]
- /api/v2/host===delete===[role2,role3,role4]
- /api/v2/host===put===[role2,role3,role4]
- /api/mi/**===put===[role2,role3,role4]
- /api/v1/getSource1===get===[role1,role2]
- /api/v2/getSource2/*/*===get===[role2]
excludedResource:
- /api/v1/source3===get
- /api/v3/host===get
- /**/*.css===get
- /**/*.ico===get
- /**/*.png===get
When we use the database schema, it is OK to read the information from the database association, and the specification returns eg: / API /v2/host=== POST ==[ROLE2, ROLE3, ROLE4]; / API /v2/host=== POST ==[ROLE2, ROLE3, ROLE4]
2. The second relevant interface of SurenessAccountProvider is the user’s account key information providing interface. We need to load the user’s account information data we want from other data sources such as database or text, and provide these data to Sureness for user authentication.
public interface SurenessAccountProvider {
SurenessAccount loadAccount(String appId);
}
This interface mainly needs to implement the above loadAccount method, which can find the user’s account information from the database or Redis cache through the user’s unique identification appid and return it. The user account information class surenessAccount is as follows:
public class DefaultAccount implements SurenessAccount {
private String appId;
private String password;
private String salt;
private List<String> ownRoles;
private boolean disabledAccount;
private boolean excessiveAttempts;
}
Simple, mainly the need to provide the user’s password related information, for Sureness authentication key to determine whether correct or not. The specific implementation of the database interface can be referred to the class DatabaseAccountProvider
Use a custom configuration to configure sureness
In the previous simple example, we used the default configuration provided by sureness, which created a new configuration class, The sureness default configuration uses the file data source sureness.yml as the data source for the account permissions. The default configuration supports JWT, Basic Auth, Digest Auth authentication
@Configuration public class SurenessConfiguration { /** * sureness default config bean * @return default config bean */ @Bean public DefaultSurenessConfig surenessConfig() { return new DefaultSurenessConfig(); }}
Before we customize sureness, let’s take a look at the general flow of sureness, so that we can understand the custom sureness configuration later. The process is as follows:
As described in the above process, the Subject is created by the request body with the SubjectCreate, and the different authentication Processor will come up with the supported Subject and then instead of using the default configuration, we will use a custom configuration to configure the sureness feature. For this custom configuration, we replace the original default file data source with the database data source. The configuration is as follows:
@Configuration public class SurenessConfiguration { @Bean ProcessorManager processorManager(SurenessAccountProvider AccountProvider) {// Processor initiates List<Processor> ProcessorList = new LinkedList<>(); // Use the default processor that supports NoneSubject noneProcessor. processorList.add(noneProcessor); JwtProcessor JwtProcessor JwtProcessor JwtProcessor JwtProcessor = new JwtProcessor(); processorList.add(jwtProcessor); // Use the default PasswordSubject-enabled processor, passwordProcessor, passwordProcessor, passwordProcessor, passwordProcessor, passwordProcessor, passwordProcessor, passwordProcessor, passwordProcessor, passwordProcessor = new PasswordProcessor(); // Note that the PasswordProcessor needs to authenticate the password of the user account, so it needs the account information provider to provide it with the desired account data. // The surenessAccountProvider accountProvider bean is the source of the account data. // The implementation bean is the DataBaseAccountProvider bean mentioned above, which is the account data provider for the database implementation. passwordProcessor.setAccountProvider(accountProvider); processorList.add(passwordProcessor); return new DefaultProcessorManager(processorList); } @bean TreePathRoleMatcher PathRoleMatcher (PathTreeProvider DatabasePathTreeProvider) {@bean TreePathRoleMatcher (PathTreeProvider DatabasePathTreeProvider) DatabasePathTreeProvider is through the database to provide resources to access configuration information under the bean instance / / we instantiate a document by sureness. Yml PathTreeProvider resource permissions provide configuration information providers documentPathTreeProvider = new DocumentPathTreeProvider(); / / below we instantiate another resource permissions by annotation form @ RequiresRoles @ WithoutAuth provide configuration information provider AnnotationPathTreeProvider AnnotationPathTreeProvider = new AnnotationPathTreeProvider(); // Set the path to the scan package. That's the controller path where you provide the API annotationPathTreeProvider.setScanPackages(Collections.singletonList("com.usthe.sureness.sample.tom.controller")); // Initialize the resource permissions matcher. We can add all three providers to the matcher to provide resource permissions data. The data in the matcher is the set of data provided by the three providers. t DefaultPathRoleMatcher pathRoleMatcher = new DefaultPathRoleMatcher(); pathRoleMatcher.setPathTreeProviderList(Arrays.asList( documentPathTreeProvider, annotationPathTreeProvider, databasePathTreeProvider)); / / use the resource access configuration data to establish the corresponding matching tree pathRoleMatcher. BuildTree (); return pathRoleMatcher; } @Bean SubjectFactory SubjectFactory () {// We already know that there are various processors that can handle the corresponding JWT, so how can we get this Subject? Different SubjectCreators are required to create corresponding Subject objects based on the request information for subsequent processes to use SubjectFactory SubjectFactory = new SurenessSubjectFactory(); / / here we register we need SubjectCreator subjectFactory. RegisterSubjectCreator (arrays.aslist (/ / attention! Mandatory must first add a noSubjectCreator new NoneSubjectServletCreator (), / / register is used to create PasswordSubject creator of new BasicSubjectServletCreator (), // register new JWTSubjectServletCreator () as the Creator used to create the JWTSubject. Implement SubjectCreate interface can be new CustomPasswdSubjectCreator ())); return subjectFactory; } @Bean SurenessSecurityManager securityManager(ProcessorManager processorManager, TreePathRoleMatcher pathRoleMatcher, SubjectFactory SubjectFactory) {// We will combine the above initialization configuration beans to initialize surenessSecurityManager surenessSecurityManager securityManager = SurenessSecurityManager.getInstance(); / / resource permissions set a match securityManager. SetPathRoleMatcher (pathRoleMatcher); / / set the subject creation factory securityManager. SetSubjectFactory (subjectFactory); / / set the CPU processor managers securityManager. SetProcessorManager (processorManager); return securityManager; }}
The surenessConfiguration configuration above explains the purpose of each configuration in detail, so we’ll summarize it here. The SubjectCreator creates the Subject, and the Processor processes the corresponding Subject.
The ProcessorManager method is the processor that provides our configuration support. Each processor requires different dependencies. For example, the PasswordProcessor needs to verify the user’s account password information. Therefore, it needs to inject the account information provider to provide it with the desired account data. Above, we injected the account information provider in the way of database.
The PathRoleMatcher method is to provide the resource path and the matching data for the supported roles. This matching data also needs to be supported by the matching data for the resource permissions. So we provide three resource permissions data providers (database, file, annotation form), and the configuration data provided by them is used in the matching data.
The SubjectFactory method is the Subject factory, and we need to register different types of Subject creation methods — that is, SubjectCreator — into the factory for different requests to create the corresponding Subject to use
The SecurityManager method consolidates all of the above configuration into one manager.
For this specific configuration example, see the SurenessConfiguration class
other
The above described the implementation of the authentication authentication project by replacing the file data source with the database data source. However, the design of the database table structure, how to provide the data interface format that Sureness wants through the design of the table data association. This can be done by referring to the Sureness integration SpringBoot sample, which provides a complete database sample implementation and corresponding table design and data.
For more customization, please visit the Sureness official website documentation: https://su.usthe.com/