前后分离项目整合spring security,自定义登录验证接口,并解决maximumSessions(1)不生效的问题 |
您所在的位置:网站首页 › loginlnfolnvalid › 前后分离项目整合spring security,自定义登录验证接口,并解决maximumSessions(1)不生效的问题 |
目录 一、引入依赖 二、编写核心配置类 1、配置类注解,以及继承父类 2、在配置类中注入所需属性 3、配置密码加密所需的bean 4、编写核心配置 5、配置登录所需的service类,以及实现加密的对象 6、解决跨域问题,并在上面的核心配置方法中配置 7、对并发session进行管理 三、定义一个保存用户信息的类,需要继承 UserDetails 接口 四、定义一个类实现UserDetailsService接口 五、定义一个类继承UsernamePasswordAuthenticationFilter 1、定义实现类,并继承接口 2、定义相关属性 3、通过构造方法来接收传入属性值 4、重写attemptAuthentication()方法,用于获取请求的json数据,实现登录功能 5、重写登录成功方法 6、重写登录失败方法 7、响应工具类 六、重写两个异常类 七、重写用户退出的处理类 八、重写未登录导致未授权的处理方法 九、定义一个类继承ConcurrentSessionFilter 十、定义一个全局异常处理类 十一、补充知识 十二、最终说明 1、Result 类 2、响应状态码 3、token问题 4、本篇文章参考 一、引入依赖首先引入 spring security 启动器的依赖 org.springframework.boot spring-boot-starter-security 二、编写核心配置类 1、配置类注解,以及继承父类 @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecuConfig extends WebSecurityConfigurerAdapter{ } 2、在配置类中注入所需属性将业务所需属性全部注入,除 redis 其他都是必须注入(我这里需要用到缓存),loginService 是自己登录实体类的service接口,根据自己项目来命名 如果 redis 不知道怎么配置,可以查看 => 整合redis并配置mybatis的二级缓存 // 在配置类中注入所需属性,传入Bean对象 @Autowired private UserDetailsService userDetailsService; @Autowired // redis private StringRedisTemplate redisTemplate; @Autowired private UserDetailsServiceImpl userDetailsServiceImpl; @Autowired // 用户实体类的service private LoginService loginService; private SessionRegistry sessionRegistry = new SessionRegistryImpl(); 3、配置密码加密所需的bean我这里没有打开密码加密,需要的话解开这个注释即可 //return new BCryptPasswordEncoder(); // 配置密码加密所需的bean @Bean public PasswordEncoder getPasswordEncoder(){ //return new BCryptPasswordEncoder(); return NoOpPasswordEncoder.getInstance(); } 4、编写核心配置其中配置了未登录导致授权失败的处理类、登出需要访问的路径、登出的处理类、以及一些过滤器、跨域的相关处理等。 我原先在这里配置了sessionManagement().maximumSessions(1),也就是不允许一个账号同时在多个地方登录,一个账号只能拥有一个session对象,但是配置了以后始终不生效,所以在后面的其他类里实现了 我这里没有加入登出相关类,因为在前端实现了,并不需要后端登出 放行的请求一般都是登录有关的请求,因为此时还没有session,如果不放行将无法访问 // 编写核心配置 @Override protected void configure(HttpSecurity http) throws Exception { http.exceptionHandling() .authenticationEntryPoint(new UnauthorizedEntryPoint()) .and().csrf().disable() //关闭csrf .authorizeRequests().antMatchers( "/basic-api/**", "/sys/basic-api/registerDept/tree").permitAll() //放行的请求路径 .anyRequest().authenticated() //.and().logout(logout -> logout.deleteCookies("JSESSIONID")).logout().logoutUrl("/sys/logout") //.addLogoutHandler(new TokenLogoutHandler()) .and() //传入bean对象给TokenLoginFilter .addFilter(new TokenLoginFilter(authenticationManager(),sessionRegistry,loginService,redisTemplate)) .addFilter(new MyConcurrentSessionFilter(sessionRegistry)) .cors().configurationSource(corsConfigurationSource()); } 5、配置登录所需的service类,以及实现加密的对象这里的service类需要后面编写自定义登录类来引入 // 配置登录所需的service类,以及实现加密的对象 @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsServiceImpl).passwordEncoder(getPasswordEncoder()); } 6、解决跨域问题,并在上面的核心配置方法中配置 // 解决跨域问题,并在上面的核心配置方法中配置 private CorsConfigurationSource corsConfigurationSource() { CorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); //同源配置,*表示任何请求都视为同源,若需指定ip和端口可以改为如“localhost:8080”,多个以“,”分隔; corsConfiguration.addAllowedHeader("*");//header,允许哪些header,本案中使用的是token,此处可将*替换为token; corsConfiguration.addAllowedMethod("*"); //允许的请求方法,PSOT、GET等 ((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**",corsConfiguration); //配置允许跨域访问的url return source; } 7、对并发session进行管理 // 对并发session进行管理 @Bean public HttpSessionEventPublisher httpSessionEventPublisher() { return new HttpSessionEventPublisher(); } 三、定义一个保存用户信息的类,需要继承 UserDetails 接口直接传入自己登录用户的实体类,然后修改 getPassword()和 getUsername()两个方法返回的值 其他方法可以暂时全部默认返回为空,具体的是用户是否启用、是否有效等等判断,可以自行编辑逻辑,我就统一在自定义登陆类里做判断了 @Data @NoArgsConstructor @AllArgsConstructor public class SecurityUser implements UserDetails { // 传入自己的登录用户实体类 private LoginOper loginOper; @Override public Collection |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |