spring security 优秀得权限控制框架 针对RABC原则设计核心功能:
认证(你是谁)
授权(你能干什么)
攻击防护(防止伪造身份)
核心组件:
SecurityContextHolder
用于存储应用程序安全上下文(Spring Context)的详细信息,如当前操作的用户对象信息、认证状态、角色权限信息等。默认情况下,SecurityContextHolder 会使用 ThreadLocal 来存储这些信息,意味着安全上下文始终可用于同一执行线程中的方法。
获取有关当前用户的信息
因为身份信息与线程是绑定的,所以可以在程序的任何地方使用静态方法获取用户信息。例如获取当前经过身份验证的用户的名称,代码如下:
Object principal =SecurityContextHolder.getContext().getAuthentication().getPrincipal();if(principal instanceof UserDetails) { String username = ((UserDetails)principal).getUsername();}else{ String username = principal.toString();}
其中,getAuthentication() 返回认证信息,getPrincipal() 返回身份信息,UserDetails 是对用户信息的封装类。
Authentication
认证信息接口,集成了 Principal 类。该接口中方法如下:
接口方法功能说明
getAuthorities()获取权限信息列表,默认是 GrantedAuthority 接口的一些实现类,通常是代表权限信息的一系列字符串
getCredentials()获取用户提交的密码凭证,用户输入的密码字符窜,在认证过后通常会被移除,用于保障安全
getDetails()获取用户详细信息,用于记录 ip、sessionid、证书序列号等值
getPrincipal()获取用户身份信息,大部分情况下返回的是 UserDetails 接口的实现类,是框架中最常用的接口之一
AuthenticationManager
认证管理器,负责验证。认证成功后,AuthenticationManager 返回一个填充了用户认证信息(包括权限信息、身份信息、详细信息等,但密码通常会被移除)的 Authentication 实例。然后再将 Authentication 设置到 SecurityContextHolder 容器中。
AuthenticationManager 接口是认证相关的核心接口,也是发起认证的入口。但它一般不直接认证,其常用实现类 ProviderManager 内部会维护一个 List<AuthenticationProvider> 列表,存放里多种认证方式,默认情况下,只需要通过一个 AuthenticationProvider 的认证,就可被认为是登录成功。
Springboot -Spring Security 相关集成
1.引入对应依赖
配置Spring securoty 核心配置
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private UserDetailsService userDetailsService; //自定义用户详情实现spring security UserDetailService接口
@Bean
public PasswordEncoder passwordEncoder() { //Spring security 密码加密器 使用不同得密钥加密
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http)throws Exception {
//禁用csrf
http.csrf().disable().headers().frameOptions().disable().and();
//配置无需验证Url
http.authorizeRequests().antMatchers("/login","/login.html").permitAll();
//配置除无需验证得URL外所有得URL必须要经过验证,并且当前用户拥有相应得权限点匹配上才可访问
http.authorizeRequests().anyRequest().access("@permissionService.hasPermission(request,authentication)").and();
//配置登录登陆请求,更改默认得参数,配置登录成功处理得Handler,和登录失败得Handler。
http.formLogin().loginPage("/login").loginProcessingUrl("/login").usernameParameter("userName").passwordParameter("password").successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,Authentication authentication)
throws IOException {
HttpSession session =request.getSession();
session.setAttribute("userInfo","测试用户信息");
response.setContentType("application/json;charset-utf-8");
PrintWriter printWriter =response.getWriter();
printWriter.write("{\"code\":00000,\"message\":\"登录成功\"}");
printWriter.close();
}
}).failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response,AuthenticationException e)
throws IOException {
response.setContentType("application/json;charset-utf-8");
PrintWriter printWriter =response.getWriter();
printWriter.write("{\"code\":40000,\"message\":\"用户名密码错误\"}");
printWriter.close();
}
//配置异常处理Handler
}).permitAll().and().exceptionHandling().accessDeniedHandler(//没有权限处理异常,登录成功之后,无权限才会触发该Handler
new AccessDeniedHandler() {
@Override
public void handle(HttpServletRequest request,
HttpServletResponse response,AccessDeniedException e)
throws IOException,ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriter printWriter =response.getWriter();
printWriter.write("{\"code\":40001,\"message\":\"无权限\"}");
printWriter.close();
}
//未登录处理异常Handler
}).authenticationEntryPoint(new AuthenticationEntryPoint() {//未登录处理异常
@Override
public void commence(HttpServletRequest httpServletRequest,
HttpServletResponse response,AuthenticationException e)
throws IOException,ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriter printWriter =response.getWriter();
printWriter.write("{\"code\":40002,\"message\":\"未登录\"}");
printWriter.close();
}
});
}
//配置登录认证
@Override
protected void configure(AuthenticationManagerBuilder auth)throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
实现Spring Security UserDetailService接口,可实现数据库版本 //可自定义实现权限点鉴权
网友评论