As long as the system and users need to be dealing with basic rights management, or improper operation to the day you delete the database how to do. Rights management framework open source has SpringSecurity, Shiro, rights management model has RBAC, ACL, etc., is to choose an open source framework for better or based rights management model was built wheels must research about the election of a suitable implementation of the company's business, first of all first research study wave SpringSecurity
By this article you will learn
SpringSecurity
Some core classes- Use
SpringSecurity
role-based permissions check SpringSecurity
Shortage
SpringSecurity core classes
Because SpringSecurity
only the research of learning, so there will not have the source code introduced. Rights Management is authorized, authentication, authorization must first sign in order to get user information, but will not be here to talk login, logout and distributed session
management, will introduce the authentication process of core classes to learn about core classes can be quickly integrated SpringSecurity
framework.
Log parity
UsernamePasswordAuthenticationFilter
=> User login authentication, but this class is really not to carry out landing check, but by ProviderManagerProviderManager
=> There is a classList<AuthenticationProvider>
, a different parity, as long as one can pass. Under normal circumstances we do not deserve what is the user name and password, this timeAuthenticationProvider
to achieve classAbstractUserDetailsAuthenticationProvider
AbstractUserDetailsAuthenticationProvider
=> Which is obtained by checking the landing subclassadditionalAuthenticationChecks
method completedDaoAuthenticationProvider
=>AbstractUserDetailsAuthenticationProvider
The only sub-category, if we set a password (may be based on memory-based database) and pass over the password validation does not check failed on landingUserDetailsService
=> Only way through this interfaceloadUserByUsername
returns the user such as user name and password information that we have set ( packaged asUserDetails
implementation class )
Summary: Login Username Password verification is to get the client's user name and password we set (that is, UserDetails
the implementation class) for comparison, to get the username and password are set by our UserDetailsService.loadUserByUsername(String userName)
realization of [the focus of planning, one would have to test] , the framework to achieve the UserDetailsService
general can not meet the project requirements, you need to manually achieved, if at the same time frame that comes with UserDetails
the realization of the class can not meet the requirements, we can also realize his UserDetails
Check permissions
FilterSecurityInterceptor
=> Role-based permissions check blocker, call the parent classAbstractSecurityInterceptor
'sbeforeInvocation
method for authenticationAbstractSecurityInterceptor
=> Call theAccessDecisionManager
implementation class ofdecide
methods for authentication, so how want to customize the way authentication can write a class and then implementAccessDecisionManager
AffirmativeBased
=> Use the defaultAccessDecisionManager
implementation class, calls theAccessDecisionVoter
vote for authentication method implementation class, returns a permission check by actually tracking the end but it is still more than the string can not be said to vote now, the method name is misleadingWebExpressionVoter
=> Use the defaultAccessDecisionVoter
implementation class, call theAuthentication的authentication
method for authenticationSecurityExpressionOperations
=> GetAuthentication
Object InterfaceSecurityExpressionRoot
=>SecurityExpressionOperations
Implementation class
Summary: Custom authentication is generally not the way, then we may not need these tubes, although the layers of calling a lot of layers, in fact, the essence is to determine the rights of the current user list included whether to include access to the url needed
SpringBoot integration SpringSecurity
rely
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>1.4.1.RELEASE</version>
</dependency>
复制代码
UserDetails implementation class: UserDTO.java
public class UserDTO implements UserDetails {
/**
* 用户名
* */
private String username;
/**
* 密码
* */
private String password;
/**
* 角色列表
* */
private List<String> roleList;
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public List<String> getRoleList() {
return roleList;
}
public void setRoleList(List<String> roleList) {
this.roleList = roleList;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorityList = new ArrayList<>();
for (String role : roleList) {
authorityList.add(new SimpleGrantedAuthority(role));
}
return authorityList;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
复制代码
Implementation class needs to implement the interface, where we will inquire into the roleList
string encapsulated SimpleGrantedAuthority
in, SimpleGrantedAuthority
it is GrantedAuthority
the realization of a class, if the default implementation can not meet the needs of their own re-implemented. UserDetail
Is SpringSecurity
a bridge between the application and, no matter how you build the database, as long as your last relationship will package the user information and permissions for UserDetails
, SpringSecurity
you can check permissions according to its own mechanisms
UserDetailsService implementation class: UserDetailsServiceImpl.java
public class UserDetailsServiceImpl implements UserDetailsService {
@Resource
private UsersService usersService;
/**
* 根据用户名获取用户信息
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Users users = new Users();
users.setUsername(username);
List<Users> usersList = usersService.selectList(users);
return buildUserDTO(usersList);
}
/**
* 封装UserDTO对象
*
* @param usersList
* @return
* */
private UserDTO buildUserDTO(List<Users> usersList) {
UserDTO userDTO = new UserDTO();
userDTO.setUsername(usersList.get(0).getUsername());
userDTO.setPassword(usersList.get(0).getPassword());
List<String> roleList = new ArrayList<>();
for (Users users : usersList) {
roleList.add(String.format("ROLE_%s", users.getRole()));
}
userDTO.setRoleList(roleList);
return userDTO;
}
}
复制代码
This class action is to find the right information and user information from the database to the package as a UserDetails
return
Permissions configuration class: WebSecurityConfig.java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级安全验证
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated() //任何请求,登录后可以访问
.and().formLogin().permitAll(); //登录页面用户任意访问
// 关闭CSRF跨域
http.csrf().disable();
}
@Override
public void configure(WebSecurity web) throws Exception {
// 设置拦截忽略文件夹,可以对静态资源放行
web.ignoring().antMatchers("/css/**", "/js/**", "/templates/**");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//1.设置自定义userDetailService
//2.校验时指定密码解码方式
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
}
复制代码
This class is well equipped with landing pages and some simple permission settings, such as access to any request after landing, everyone can access the login page. Because by the @EnableGlobalMethodSecurity
open method of verifying the level of annotation, method-level permission is not configured In this method. At the same time achieved by specifying their own UserDetailsService
and password to decode the way, if you do not specify a password will be thrown in the way of decoding the latest SpringSecurity
version
Use control layer annotations
@RestController
@RequestMapping("/api/user")
public class UsersController {
@GetMapping("/guest")
@PreAuthorize("hasAnyRole('guest')")
public Object guest() {
return "hello guest";
}
@PreAuthorize("hasAnyRole('admin')")
@GetMapping("/admin")
public Object admin() {
return "hello admin";
}
}
复制代码
Through @PreAuthorize
to access control, the hasAnyRole
access to the api has permission (role) is written, in addition to using @PreAuthorize
notes, you can also use @Secured
, @PostAuthorize
annotations
Insufficient SpringSecurity framework
-
Project code has invaded
-
Not general enough, all the required permissions verification systems require integration
SpringSecurity
framework, different application systems database design,UserDetail
it generally takes to achieve their own [just an example, the actual development process to rewrite the class probably more] -
Role should be dynamic, but by
SpringSecurity
the role configuration is static, you must modify the code in the database added a new role, otherwise it can not be used -
Not a
RBAC
design model but aACL
model, clarify roles privileges not particularly clear, the role of authority may be, if you want based onRBAC
the permissions check must re-write their own permission check method -
Rights management granularity is not detailed enough, can not support such a method to check the level of authority, I want to support more fine-grained permissions must write their own check permissions
-
Three ways to cache user information provided, respectively
NullUserCache
,EhCacheBasedUserCache
,SpringCacheBasedUserCache
. The first foreverreturn null
, the equivalent of not using the cache, the latter two are memory cache, the cache hit rate will appear in a distributed deployment, the cache inconsistency, the need to implement cacheOnly some of his views, please correct me if flawed
Last Attachment: Project Source