前面我们弄好了认证,授权就是在认证的基础之上
授权
只有用户认证了才可能有授权,授权就是当前用户能干什么
UserDetailServiceImpl
// 之前我们只是在这里将用户的一些基本信息封装了,但是我们要授权的话需要角色信息和权限信息
// TODO 添加持久层的代码 获取当前用户的角色和权限信息
TokenFilter
// 在对UsernamePasswordAuthenticationToken封装的时候,没有将对象中的权限封装进去
// TODO 调用UserDetail中的getAuthorities方法,这个方法返回GrantedAuthority
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, null,loginUser.getAuthorities());
启动类
添加@EnableGlobalMethodSecurity(prePostEnabled = true)注解
Controller
在Controller层中的方法上添加 @PreAuthorize("hasAuthority('权限名')") @PreAuthorize("hasAuthority('权限名')") 用户有这个权限才能访问 @PreAuthorize("hasRole('角色名')") 用户是当前角色才能访问
RBAC模型
基于角色进行权限控制,这个时候我们不关心当前用户有哪些权限。只用关系当前用户有哪些角色
RBAC表设计
- tb_security_user_role
- id
- user_id
- role_id
- tb_security_role
- id
- role_name
- tb_security_role_permission
- id
- role_id
- permission_id
- tb_security_permission
- id
- permission_name
其他
自定义处理异常
当发送异常的时候,SepringSecurity会自动处理掉。因为我们是前后端分离我们不用管处理的逻辑只用返回一个Result的json字符串返回给前端,前端自己处理
{
"code" : "xxx",
"msg" : "xxx",
"status" : "xxx",
"data" : [
"key" : "value"
]
}
自定义处理认证时发送的异常
@Component
// 认证期间异常处理
public class AuthenticationExceptionHandler implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
Result result = Result.fail().data("msg", authException.getMessage());
String resultJSON = JSONUtil.toJsonStr(result);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
writer.append(resultJSON);
}
}
自定义授权时发生的异常
@Component
// 处理授权异常的
public class AuthorizationExceptionHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
Result result = Result.fail().data("msg", accessDeniedException.getMessage());
String resultJSON = JSONUtil.toJsonStr(result);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
writer.append(resultJSON);
}
}
将自定义的处理异常对象添加到配置类中 SecurityConfig
// 自定义异常处理
http.exceptionHandling()
.authenticationEntryPoint(authenticationExceptionHandler)
.accessDeniedHandler(authorizationExceptionHandler);
跨域
解决Spring Security跨域 SecurityConfig
// 跨域
http.cors();
解决MVC跨域
@Configuration
public class CorsConfig {
@Bean
public CorsConfigurationSource corsFilterConfiguration() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin("*"); // 允许所有源
configuration.addAllowedHeader("*"); // 允许所有请求头
configuration.addAllowedMethod("*"); // 允许所有请求方法
configuration.setAllowCredentials(true); // 允许发送凭证
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration); // 对所有URL生效
return source;
}
}