spring-security实现角色权限的控制
spring-security提供了方便的权限控制方法,我们只需进行简单的配置就可以实现而不再需要使用「硬代码」的方式来进行编写。
这样开发人员就可以专注于业务逻辑的编写。
访问url按照用户角色进行授权
请先访问我以前写的前后端分离的实现spring-security实现前后端分离登录
在以上的基础上再进行授权的访问分配。
@Configuration
@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private PasswordEncoder myPasswordEncoder;
private CustomUserService myCustomUserService;
private ObjectMapper objectMapper;
public SecurityConfig(CustomUserService myCustomUserService, ObjectMapper objectMapper) {
this.myPasswordEncoder =new BCryptPasswordEncoder();
this.myCustomUserService = myCustomUserService;
this.objectMapper = objectMapper;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authenticationProvider(authenticationProvider())
.httpBasic()
//未登录时,进行json格式的提示,很喜欢这种写法,不用单独写一个又一个的类
.authenticationEntryPoint((request,response,authException) -> {
response.setContentType("application/json;charset=utf-8");
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
PrintWriter out = response.getWriter();
Map<String,Object> map = new HashMap<String,Object>();
map.put("code",403);
map.put("message","未登录");
out.write(objectMapper.writeValueAsString(map));
out.flush();
out.close();
})
.and()
.authorizeRequests()
// user访问下的所有url,只有ADMIN才能够进行访问
.antMatchers("/user/**").hasRole("ADMIN")
.anyRequest().authenticated() //必须授权才能范围
.and()
.formLogin() //使用自带的登录
.permitAll()
//登录失败,返回json
.failureHandler((request,response,ex) -> {
response.setContentType("application/json;charset=utf-8");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter out = response.getWriter();
Map<String,Object> map = new HashMap<String,Object>();
map.put("code",401);
if (ex instanceof UsernameNotFoundException || ex instanceof BadCredentialsException) {
map.put("message","用户名或密码错误");
} else if (ex instanceof DisabledException) {
map.put("message","账户被禁用");
} else {
map.put("message","登录失败!");
}
out.write(objectMapper.writeValueAsString(map));
out.flush();
out.close();
})
//登录成功,返回json
.successHandler((request,response,authentication) -> {
Map<String,Object> map = new HashMap<String,Object>();
map.put("code",200);
map.put("message","登录成功");
map.put("data",authentication);
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.write(objectMapper.writeValueAsString(map));
out.flush();
out.close();
})
.and()
.exceptionHandling()
//没有权限,返回json
.accessDeniedHandler((request,response,ex) -> {
response.setContentType("application/json;charset=utf-8");
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
PrintWriter out = response.getWriter();
Map<String,Object> map = new HashMap<String,Object>();
map.put("code",403);
map.put("message", "权限不足");
out.write(objectMapper.writeValueAsString(map));
out.flush();
out.close();
})
.and()
.logout()
//退出成功,返回json
.logoutSuccessHandler((request,response,authentication) -> {
Map<String,Object> map = new HashMap<String,Object>();
map.put("code",200);
map.put("message","退出成功");
map.put("data",authentication);
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.write(objectMapper.writeValueAsString(map));
out.flush();
out.close();
})
.permitAll();
//开启跨域访问
http.cors().disable();
//开启模拟请求,比如API POST测试工具的测试,不开启时,API POST为报403错误
http.csrf().disable();
}
@Override
public void configure(WebSecurity web) {
//对于在header里面增加token等类似情况,放行所有OPTIONS请求。
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
//对默认的UserDetailsService进行覆盖
authenticationProvider.setUserDetailsService(myCustomUserService);
authenticationProvider.setPasswordEncoder(myPasswordEncoder);
return authenticationProvider;
}
}
根据用户的角色进行判断是否有权限进行访问
创建role实体类,并且实现GrantedAuthority接口
public class RolePo implements GrantedAuthority {
// 这里为了方便进行测试,所以写成了固定的角色
private String role="ROLE_ADMIN";
@Override
public String getAuthority() {
return this.getRole();
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
User实体类实现UserDetail接口,并重写getAuthorities方法。
public class SysUserPo implements UserDetails {
@TableId(type = IdType.AUTO)
private Integer id;
@TableField(value ="user_name")
private String userName;
@TableField(value = "password")
private String password;
@TableField(value = "role")
private String role;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> auths = new ArrayList<>();
RolePo role=new RolePo();
auths.add(role);
return auths;
}
@Override
public String getUsername() {
System.out.println(this.userName);
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;
}
}
进行测试
@RequestMapping("/user")
@RestController
public class UserController {
@GetMapping("/get")
public String getUser(){
return "bulingfeng";
}
}
访问http://127.0.0.1:8080/user/get。能够访问到数据。
修改role中的默认值,比如修改成ROLE_USER。再次启动并且访问,返回403 forbiden。