Spring Secutity and Apache Shiro are the two mainstream open source security frameworks in the Java field, and they are also the main technology selections for permission system design. This article mainly introduces the implementation principle of Spring Secutity, and designs a permission system based on RBAC based on Spring Secutity.
1. Technology selection
Why Spring Secutity is used as the technology selection of the authorization system, the following aspects are mainly considered:
- Data authentication capability: Spring Secutity supports data authentication, that is, fine-grained authority control.
- Spring Ecological Basis: Spring Secutity can be seamlessly integrated with Spring ecology.
- Multiple authentication capabilities: Spring Secutity supports multiple authentication methods, such as pre-authentication methods that can be integrated with third-party authentication systems.
Spring Security | Apache Shiro | |
---|---|---|
Authentication | Support multiple authentication methods (such as password, Anonymous, Pre-authentication) | Simple login authentication |
Authentication | Function authentication, Data authentication | Function authentication |
Multi-source adaptation | Mem, JDBC, DAO, LDAP, OpenID, OAuth, etc. |
LDAP, JDBC, Kerberos, ActiveDirectory, etc. |
Encryption | Support multiple encryption methods | Simple encryption method |
Operating environment | Rely on Spring | Can run independently |
Openness | Open source, Spring ecological foundation | Open source |
Complexity | Complex and heavier< /td> | Simple and flexible |
Second, core architecture
Permission system generally includes Two core modules: Authentication and Authorization.
- Authentication: The authentication module is responsible for verifying the legitimacy of the user’s identity, generating an authentication token, and saving it to the server session (such as TLS).
- Authentication: The authentication module is responsible for obtaining user identity information from the server session, and comparing it with the accessed resources.
The official Spring Security core architecture diagram is as follows:
Interpretation of the core architecture:
- AuthenticationManager: Responsible for authentication management, parsing user login information (encapsulated in Authentication), reading Take user, role, and permission information for authentication, and the authentication result is backfilled into Authentication and stored in SecurityContext.
- AccessDecisionManager: Responsible for authentication voting, summarizing the results of the voter, and realizing the one-vote (default), multiple-vote, and one-vote veto strategy.
- SecurityInterceptor: Responsible for permission interception, including Web URL interception and method call interception. Obtain the description information of the resource through ConfigAttributes, and perform authentication interception with the aid of AccessDecisionManager.
- SecurityContext: Security context, save the authentication result. Three strategies are provided: global context, thread inheritance context, and thread independent context (default).
- Authentication: authentication information, save the user’s identity mark, permission list, certificate, authentication mark and other information.
- SecuredResource: Resources that are under security control, such as Web URLs, users, roles, custom domain objects, etc.
- ConfigAttributes: Resource attribute configuration, describing the information of security management and control resources, and providing the input of interception logic for SecurityInterceptor.
Three. Design Principles
Through the analysis of the source code, I put together the core domain model design of Spring Security as follows:
Interpretation of the global abstract model:
- Configuration: AuthenticationConfiguration is responsible for the global configuration of the authentication system, and GlobalMethodSecurityConfiguration is responsible for the global configuration of method call interception.
- Build: AuthenticationConfiguration builds AuthenticationManager through AuthenticationManagerBuilder, GlobalMethodSecurityConfiguration will automatically initialize AbstractSecurityInterceptor for method call interception.
- Web interception: HttpSecurity performs security configuration on the Web, with a large number of built-in GenericFilterBean filters to intercept URLs. The filter responsible for authentication will be authenticated through the AuthenticationManager and the authentication result will be stored in the SecurityContext.
- Method interception: Spring uses AOP technology (cglib/aspectj) to intercept methods marked as @PreAuthorize, @PreFilter, @PostAuthorize, @PostFilter and other annotations, and call them through AbstractSecurityInterceptor AuthenticationManager performs authentication (if necessary).
- Authentication: Authentication Manager AuthenticationManager has built-in multiple authenticators AuthenticationProvider, as long as one of the authentication passes, the authentication will be successful. Different AuthenticationProviders obtain the information they need (HTTP requests, database queries, remote services, etc.) for authentication, and the authentication results are all encapsulated in Authentication. Authenticators that need to load user, role, and permission information (such as password authentication, pre-authentication, etc.) need to be connected to the UserDetailsManager interface to implement the user CRUD function.
- Authentication: The permission interceptor AbstractSecurityInterceptor loads the description information ConfigAttribute of the resource that needs to be authenticated by reading different SecurityMetadataSource, and then combines the authentication information Authentication, resource description ConfigAttribute, resource object It is passed to AccessDecisionManager for voting. AccessDecisionManager has built-in multiple voting devices AccessDecisionVoter. The voting device converts the ConfigAttribute in the authentication information into the SpringEL format, and executes the expression-based authentication logic through the expression processor SecurityExpressionHandler, and the authentication logic is forwarded to by reflection Each operation of SecurityExpressionRoot goes up.
- Customization: HTTP security configuration HttpSecurity and authentication manager builder AuthenticationManagerBuilder can be customized through WebSecurityConfigureAdapter; pre-authentication filters can be customized through AbstractPreAuthenticatedProcessingFilter; customization can be docked through UserDetailsManager and UserDetails interfaces Data source; Customize permission information through GrantedAuthority; Customize the access control logic of a custom domain model through PermissionEvaluator.
Fourth, application integration
After clarifying the customization points of Spring Security, you can integrate Spring Security within the system.
Pre-authentication is used here to adapt to third-party authentication systems. AbstractPreAuthenticatedProcessingFilter provides extension points for pre-authentication, and implements a custom authentication filter based on this abstract class.
public class MyPreAuthFilter extends AbstractPreAuthenticatedProcessingFilter {@Override protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {// Obtain the user ID from a third-party system return userId;} @Override protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {return ""; }}
Spring Security will load initial information such as user roles based on the user ID information returned by the pre-authentication filter getPreAuthenticatedPrincipal. Here you need to implement the UserDetailsManager interface to provide a user information manager.
@Servicepublic class MyUserManager implements UserDetailsManager {@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// Load user information from the database return user;} // Other management interfaces} pre>UserDetails contains the authorization information abstraction of the GrantedAuthority interface type, and generally you can customize roles and permissions based on it. Spring Security uses an interface form to express roles and permissions. The difference between roles and permissions is that the ID of a role is prefixed with "ROLE_".
public class MyRole implements GrantedAuthority {private final String role; @Override public String getAuthority() {return "ROLE_" + role; }}public class MyAuthority implements GrantedAuthority {private final String authority ; @Override public String getAuthority() {return authority; }}Next, register a custom authentication filter and user manager. Here you need to implement WebSecurityConfigurerAdapter for Web security configuration.
@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.PROXY) public class MySecurityConfig extends WebSecurityConfigurerAdapter {@Autowired UserDetailsManager userDetailsManager; @Bean protected AuthenticationProvider createPreAuthProvider() {// Registered user Manager PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider(); provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>(userDetailsManager)); return provider;} @Override protected void configure(HttpSecurity http) throws Exception {// Register a pre-authentication filter http.addFilter( new MyPreAuthFilter(authenticationManager())); }}In this way, the simplest Spring Security framework integration within the system has been completed. The following methods can be used for authentication on any service interface of the system.
public interface MyService {@PreAuthorize("hasAuthority('QUERY')") Object getById(String id); @PreAuthorize("hasRole('ADMIN')") void deleteById(String id);}The PreAuthorize annotation means pre-call authentication. Spring uses dynamic proxy technology to generate authentication logic by default. SpringEL expressions are configured in the annotations to customize the authentication method. In the above code, hasAuthority will check whether the user has the QUERY permission, and hasRole will check whether the user has the ADMIN role.
Using the dynamic proxy method for AOP, only allows permission interception at the interface level. If you want to perform permission interception on any method, you need to use AspectJ to perform AOP. First, set the mode of the annotation EnableGlobalMethodSecurity to AdviceMode.ASPECTJ, and then add the JVM startup parameters, so that you can use Spring Security annotations on any method.
-javaagent:/path/to/org/aspectj/aspectjweaver/1.9.4/aspectjweaver-1.9.4.jarThe above is still only for the user Identity information (role/authority) has limited flexibility, and it cannot give full play to the data authentication capabilities of Spring Security. To use data authentication, you need to implement a Spring Bean.
@Componentpublic class MyPermissionEvaluator implements PermissionEvaluator {@Override public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {// Custom data authentication return false;} @Override public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {// Custom data authentication return false; }}PermissionEvaluator will be automatically registered to the Spring Security framework and allowed to be used in annotations Perform authentication as follows.
@PreAuthorize("hasPermission(#id,'QUERY')")Object func1(String id) {}@PreAuthorize("hasPermission(#id,'TABLE','QUERY ')")Object func2(String id) {}Among them, the annotation of func1 indicates to verify whether the user has QUERY permission to the id, and the code logic is routed to the first interface of MyPermissionEvaluator. The annotation of func2 means to verify whether the user has QUERY permission for the TABLE type id, and the code logic is routed to the second interface of MyPermissionEvaluator. PermissionEvaluator provides an extension point for data authentication in the permission system. How to use this extension point to customize an RBAC-based permission system will be described later.
Five, permissions system
To build a permissions system based on RBAC (Role Based Access Control), it is necessary to clarify users, roles, permissions, and resources. The meaning of the core concept classes and the relationship between them.
- Resources: Objects in the permission system that need security control, generally data or functions in the system.
- Permission: Describes the abstraction of operations on the resource, which is generally an action.
- Authorization: It is a combination of permissions and resources, which means a certain operation on resources.
- Role: Describes a set of authorizations and represents a set of special concepts.
- User: The main body of the permission system, generally the access user of the current system, and the user can have multiple roles.
The following is our RABC-based authorization core domain model:
Under normal circumstances, the resources that require permission control in the system cannot be customized by users. Because resources are coupled with a large amount of business logic, we provide a self-resource factory through configuration The resources needed to construct the business module in a standardized manner. Users, roles, permissions, and authorization records can all be queried and updated through the corresponding manager.
In addition, resource abstraction allows to express the inheritance and combination of resources, and then express more complex resource models. The process of unified resource authentication is:
- When performing authentication, first look at whether the resource is an atomic resource or a composite resource.
- For atomic resources, first check whether there is an authorization record, and then check whether the role pre-authorization includes the current authorization. If one exists, it will succeed.
- Atomic resources without authorization records and role pre-authorization, try to use the parent resource (if any) instead of authentication, otherwise the authentication fails.
- For combined resources, first expand the resources to obtain a list of sub-resources.
- Traverse the list of sub-resources, and authenticate the sub-resources in turn. After the sub-resource authentication results are summarized, the resource authentication results are combined.
To sum up, based on the unified resource abstraction and resource configuration construction, the unified construction of resources can be realized, and then the unified authentication can be realized.
6. Summary review
This article starts from the architecture and principles of Spring Security, and describes the design ideas and design ideas of the open source security framework for authentication and authentication modules. detail. It also provides a method to integrate Spring Security in the system, combined with the RBAC general permission system model, discusses the design and implementation of unified resource construction and unified authentication. If you also need to design a new permission system, I hope this article will help you.