springsecurity轻松实现角色权限

问题:

如何在springboot项目中使用springsecurity去实现角色权限管理呢?本文将尽可能简单的一步步实现对接口的角色权限管理。

项目框架:

springsecurity轻松实现角色权限_第1张图片

sql:

user表:

CREATE TABLE `user` (
  `Id` int NOT NULL AUTO_INCREMENT,
  `UserName` varchar(255) NOT NULL,
  `CreatedDT` datetime DEFAULT NULL,
  `Age` int DEFAULT NULL,
  `Gender` int DEFAULT NULL,
  `Password` varchar(255) NOT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

role表:

CREATE TABLE `role` (
  `Id` int NOT NULL AUTO_INCREMENT,
  `UserId` int DEFAULT NULL,
  `Role` varchar(255) DEFAULT NULL,
  `CreatedDT` datetime DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

maven:

在pom.xml中加入

        
            org.projectlombok
            lombok
            true
        
        
        
            org.springframework.boot
            spring-boot-starter-security
        
        
        
            cn.hutool
            hutool-all
            4.5.7
        

model:

实体类User要实现springsecurity的基本接口UserDetails,UserDetails里继承了Serializable,不用担心序列化

@Data  
public class User implements UserDetails {  
​  
 public User() {  
 }  
​  
 private static final long serialVersionUID = 1L;  
   
 private Integer  id;  
​  
 private String  userName;  
​  
 private Date  createdDT;  
​  
 private Integer  age;  
​  
 private Integer  gender;  
​  
 private String passWord;  
​  
 private String role;  
​  
 private List authorities;  
​  
 public User(String userName, String passWord, List authorities) {  
 this.userName = userName;  
 this.passWord = passWord;  
 this.authorities = authorities;  
 }  
​  
 @Override  
 public Collection getAuthorities() {  
 return authorities;  
 }  
​  
 @Override  
 public String getPassword() {  
 return this.passWord;  
 }  
​  
 @Override  
 public String getUsername() {  
 return this.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;  
 }  
}  
​

实体类role:

@Data  
public class Role implements Serializable {  
 private Integer id;  
​  
 private String role;  
​  
 private Date createdDT;  
​  
 private Integer userId;  
}  
​

mapper:

@Mapper  
public interface UserMapper{  
 User selectOneByName(User user);  
}

service:

public interface UserService{  
 User selectOneByName(User user) throws ServiceException;  
}

serviceImpl:

@Service  
public class UserServiceImpl implements UserService {  
 @Autowired  
 private UserMapper mapper;  
​  
 @Override  
 public User selectOneByName(User user) throws ServiceException {  
 return mapper.selectOneByName(user);  
 }  
}

mapper.xml:

  
  
  
   
   
   
   
   
   
   
   
 Id, UserName, CreatedDT, Age, Gender,Password  
   
   
   

config:

首先实现UserDetailsService类。自定义获取用户信息和角色信息。

@Component  
public class CustomUserDetailsService implements UserDetailsService {  
 @Autowired  
 private UserService userService;  
​  
 @Autowired  
 private HttpServletRequest request;  
​  
 @Override  
 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {  
 // 通过用户名从数据库获取用户信息  
 User user = userService.selectOneByName(new User(){  
 {  
 setUserName(username);  
 }  
 });  
 if (user == null) {  
 throw new UsernameNotFoundException("用户不存在");  
 }  
​  
 HttpSession session = request.getSession();  
 session.setAttribute(session.getId(),user);  
​  
 // 得到用户角色  
 String role = user.getRole();  
​  
 // 角色集合  
 List authorities = new ArrayList<>();  
 // 角色必须以`ROLE_`开头,数据库中没有,则在这里加  
 authorities.add(new SimpleGrantedAuthority("ROLE_" + role));  
​  
 return new User(  
 user.getUsername(),  
 user.getPassword(),  
 authorities  
 );  
 }  
}

自定义错误提示

@Component  
public class MyAccessDeniedHandler implements AccessDeniedHandler {  
 @Override  
 public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {  
 response.setCharacterEncoding("UTF-8");  
 response.setContentType("application/json");  
 response.getWriter().println("{'code':'403','message':'没有访问权限'}");  
 response.getWriter().flush();  
 }  
}

终于来到security的配置了

@EnableWebSecurity  
@EnableGlobalMethodSecurity(prePostEnabled = true)  
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {  
 @Autowired  
 private CustomUserDetailsService userDatailService;  
​  
 @Autowired  
 private MyAccessDeniedHandler accessDeniedHandler;  
​  
 @Bean  
 public PasswordEncoder passwordEncoder(){  
 return new BCryptPasswordEncoder();  
 }  
​  
 @Override  
 protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
 auth  
 .userDetailsService(userDatailService)  
 .passwordEncoder(passwordEncoder());  
 }  
​  
​  
 @Override  
 protected void configure(HttpSecurity http) throws Exception {  
 http  
 .headers().frameOptions().disable()  
 .and()  
 .authorizeRequests()  
 .antMatchers("不限制访问的路径,如:'/user/*'").permitAll()  
 .antMatchers("用户拥有规定角色才允许访问的路径,如:'/user/delte'").hasRole("admin")  
 .antMatchers("规定ip才允许访问的路径,如:'/*'").hasIpAddress("192.168.1.1/24");  
 .anyRequest().authenticated() // 所有请求都需要验证  
 .and()  
 // 跳转自定义成功页  
 .formLogin().defaultSuccessUrl("/html/index.html")  
 .and()  
 .exceptionHandling()  
 //用户无权限访问链接,给出友好提示  
 .accessDeniedHandler(accessDeniedHandler)  
 .and()  
 .csrf().disable();// post请求要关闭csrf验证,不然访问报错;实际开发中要开启。  
 }  
}

至此,springsecurity的角色权限管理就完成了,如果想要实现方法级的角色权限限制,可以在方法前加入 @PreAuthorize("hasRole('角色')")注解,多个角色可以使用hasAnyRole(),就可以限制拥有规定角色权限的用户才能访问了。

 @PreAuthorize("hasRole('admin')")  
 @RequestMapping(value = "/delete")  
 public CommonResult delete(@RequestBody int id) {  
     int i = userService.delete(new User() {  
     {  
        setId(id);  
     }  
     });  
     return i > 0 ? processSuccess("删除成功") : processFailure("删除失败");  
 }

你可能感兴趣的