spring security
spring security 主要的两个功能是认证和授权
认证的大概流程:
Username password AuthenticationFilter(自定义usernamepassword拦截器)
UserDetailService (查询用户密码的service接口)
Userdetails (用户类接口)
AuthenticationProvide (为认证管理器AuthenticationManager 提供验证组件AuthenticationProvider)
授权的大概流程:
(extends)AbstractsecurityInterceptor +(implements)Filter(资源访问过滤器,拦截访问请求,封装成安全对象FilterInvocation,调用前两个实例进行鉴权)
FilterInvocationSecurityMetadataSource(自定义权限数据源,提供所有URL资源与对应角色权限的映射集合)
AccessDecisionManager (自定义鉴权管理器,根据URL资源权限和用户角色权限进行鉴权)
用户登陆
会被AuthenticationProcessingFilter拦截,调用AuthenticationManager的实现,而且AuthenticationManager会调用ProviderManager来获取用户验证信息(不同的Provider调用的服务不同,因为这些信息可以是在数据库上,可以是在LDAP服务器上,可以是xml配置文件上等),如果验证通过后会将用户的权限信息封装一个User放到spring的全局缓存SecurityContextHolder中,以备后面访问资源时使用。
访问资源(即授权管理)
访问url时,会通过AbstractSecurityInterceptor拦截器拦截,其中会调用FilterInvocationSecurityMetadataSource的方法来获取被拦截url所需的全部权限,在调用授权管理器AccessDecisionManager,这个授权管理器会通过spring的全局缓存SecurityContextHolder获取用户的权限信息,还会获取被拦截的url和被拦截url所需的全部权限,然后根据所配的策略(有:一票决定,一票否定,少数服从多数等),如果权限足够,则返回,权限不够则报错并调用权限不足页面。
项目结构:
数据库设计:
model:
Permission
package com.example.arcgisdemo.model;
import com.sun.javafx.beans.IDProperty;
import javax.persistence.*;
import java.util.List;
@Entity
@Table(name = "SYS_PERMISSION")
public class Permission {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private int id;
@Column(name = "NAME")
private String name;
@Column(name = "DESCRIPTION")
private String description;
@Column(name = "URL")
private String url;
@Column(name = "PID")
private String pid;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
}
User:
这里是在User中实现了UserDetails
package com.example.arcgisdemo.model;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Entity
@Table(name = "SYS_USER")
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private int id;
@Column(name = "USERNAME")
private String username;
@Column(name = "PASSWORD")
private String password;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "SYS_ROLE_USER",
joinColumns = {@JoinColumn(name = "SYS_USER_ID",referencedColumnName = "ID")},
inverseJoinColumns = {@JoinColumn(name = "SYS_ROLE_ID",referencedColumnName = "ID")})
private List<Role> roles;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
if (roles == null || roles.size() < 1) {
return AuthorityUtils.commaSeparatedStringToAuthorityList("");
}
StringBuilder rolestring = new StringBuilder();
for (Role role : roles) {
rolestring.append(role.getName()).append(",");
}
List<GrantedAuthority> authorityList = AuthorityUtils.commaSeparatedStringToAuthorityList(rolestring.substring(0, rolestring.length() - 1));
return authorityList;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public List<Role&