以下内容学习自微信公众号“江南一点雨”
1、引入springSecurity
<!-- spring security依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>1.5.3.RELEASE</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.17</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.5</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
2、建表
2.1 user用户表
2.2 role角色表
2.3 menu菜单表
2.4 user_role用户角色关系表
2.5 role_menu菜单角色关系表
3、建立user、role、menu对应实体类,其中user类实现org.springframework.security.core.userdetails.UserDetails接口
public class User implements UserDetails {
private Integer id;
private String username;
private String password;
private boolean isEnabled;
private List<Role> roles;
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public Integer getId() {
return id;
}
public void setId(Integer 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;
}
public void setEnabled(boolean enabled) {
isEnabled = enabled;
}
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> authority = new ArrayList<SimpleGrantedAuthority>();
for (Role role : roles) {
authority.add(new SimpleGrantedAuthority(role.getRoleName()));
}
return authority;
}
public boolean isAccountNonExpired() {
return true;
}
public boolean isAccountNonLocked() {
return true;
}
public boolean isCredentialsNonExpired() {
return true;
}
public boolean isEnabled() {
return isEnabled;
}
4、新建UserService类实现接口org.springframework.security.core.userdetails.UserDetailsService
@Service
public class UserService implements UserDetailsService {
@Autowired
UserMapper userMapper;
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userMapper.loadUserByUsername(username);
if(user==null){
throw new UsernameNotFoundException("用户不存在");
}
user.setRoles(userMapper.getRolesByUserId(user.getId()));
return user;
}
}
5、新建MyFilter类实现org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource,找出所有能访问当前请求路径的角色
@Component
public class MyFilter implements FilterInvocationSecurityMetadataSource {
AntPathMatcher antPathMatcher = new AntPathMatcher();
@Autowired
MenuMapper menuMapper;
public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
//请求的地址路径
String requestUrl = ((FilterInvocation) o).getRequestUrl();
//所有菜单资源地址路径
List<Menu> menus = menuMapper.getAllMenus();
for (Menu menu : menus) {
//请求路径与菜单路径匹配的上,则查看访问该菜单需要哪些角色
if(antPathMatcher.match(menu.getMenuResource(),requestUrl)){
List<Role> roles= menu.getRoles();
String[] strRoles = new String[roles.size()];
for (int i = 0; i < roles.size(); i++) {
strRoles[i] = roles.get(i).getRoleName();
}
return SecurityConfig.createList(strRoles);
}
}
//其他路径
return SecurityConfig.createList("ROLE_login");
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
public boolean supports(Class<?> aClass) {
return true;
}
}
6、新建MyAccessDecisionManager类实现org.springframework.security.access.AccessDecisionManager,根据当前用户角色,判断是否有能访问当前请求路径的
@Component
public class MyAccessDecisionManager implements AccessDecisionManager {
public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
//collection是请求该资源需要的所有角色
for (ConfigAttribute configAttribute : collection) {
//登录之后就可以访问
if(("ROLE_login").equals(configAttribute.getAttribute())){
//匿名用户,即未登录
if(authentication instanceof AnonymousAuthenticationToken){
throw new AccessDeniedException("非法请求");
}else{
return;
}
}
//authorities当前登录用户所拥有的角色
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (GrantedAuthority authority : authorities) {
//当前登录用户存在请求资源所需的角色
if(configAttribute.getAttribute().equals(authority.getAuthority())){
return;
}
}
}
throw new AccessDeniedException("非法请求");
}
public boolean supports(ConfigAttribute configAttribute) {
return true;
}
public boolean supports(Class<?> aClass) {
return true;
}
}
7、新建MySecurityConfig类实现org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserService userService;
@Autowired
MyFilter myFilter;
@Autowired
MyAccessDecisionManager myAccessDecisionManager;
//密码加密方式
@Bean
public PasswordEncoder setPasswordEncoder(){
return new BCryptPasswordEncoder();
}
//验证用户名密码是否正确
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
public <O extends FilterSecurityInterceptor> O postProcess(O o){
o.setAccessDecisionManager(myAccessDecisionManager);
o.setSecurityMetadataSource(myFilter);
return o;
}
})
.and()
.formLogin().permitAll()
.and()
.csrf().disable();
}
}
8、测试
@RestController
public class HelloController {
@Autowired
UserMapper userMapper;
@GetMapping("/hello")
public String hello(){
return userMapper.getUserById(1).toString();
}
@GetMapping("/dba/hello")
public String hellodba(){
return "hello dba";
}
@GetMapping("/admin/hello")
public String helloadmin(){
return "hello admin";
}
@GetMapping("/user/hello")
public String hellouser(){
return "hello user";
}
}
8.1 localhost:8888/hello 登录后所有用户都可以访问
8.2 localhost:8888/dba/hello 只有有数据库管理员角色的用户登录后才可以访问
8.3 localhost:8888/admin/hello 只有有系统管理员角色的用户登录后才可以访问
8.4 localhost:8888/user/hello 只有有普通用户角色的用户登录后才可以访问