/** * @Author fei * @Date 2021/1/2 3:43 下午 * * @Configuration用于定义配置类,定义的配置类可以替换xml文件,一般和@Bean注解联合使用。 * @Configuration注解主要标注在某个类上,相当于xml配置文件中的<beans> * @Bean注解主要标注在某个方法上,相当于xml配置文件中的<bean> */ @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { /** * 必须要有这个实例 NoOpPasswordEncoder.getInstance() 这是一个过期的方法。 * @return */ @Bean PasswordEncoder passwordEncoder(){ return NoOpPasswordEncoder.getInstance();//获取这个不加密的实例 为了下面的用户名对应的密码不加密 直接123就可以登录 } /** * 设置用户和密码 以及角色 * @param auth * @throws Exception */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //在内存中配置密码 auth.inMemoryAuthentication() .withUser("ppf").password("123").roles("admin") .and() .withUser("ask").password("123").roles("user"); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //开启授权方法 .antMatchers("/admin/**").hasRole("admin") //匹配器,在/admin/**这个地址要进行权限配置,赋予一个角色 admin //.antMatchers("user/**").hasAnyRole("admin","user") //hasAnyRole 表示具备这两个角色其中一个就可以 .antMatchers("/user/**").access("hasAnyRole('user','admin')") //这个和上面的一个意思 .anyRequest().authenticated() //anyRequest 表示其他没有需要授权的地址,登录之后就能访问。 authenticated 已验证的 登录之后能访问 .and() .formLogin() //上面配完之后呢,下面还需要配置表单登录 .loginProcessingUrl("/doLogin") //表示处理登录请求的url 这个配不配都可以,主要是方便用postman 来测试接口时用 .loginPage("/login") //这个表示需要登录,则跳转到/login这个url 一般前后端分离 不需要配置这个 .usernameParameter("uname") //这个表示 讲username这个属性名字改成uname,密码也是同理 .passwordParameter("passwd") //所以接口就应该这样写 http://localhost:8080/doLogin?uname=ppf&passwd=123 一般来说这个没有必要配置 //successHandler 表示前后端分离的项目,登录成功后,需要跳转的页面,这时候,后端只要返回json给前端(登录成功的一个处理器) .successHandler(new AuthenticationSuccessHandler() { @Override //参数 authentication 是保存了登录成功的用户信息 public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException { resp.setContentType("application/json;chartset=utf-8"); //设置要返回的json格式 PrintWriter out = resp.getWriter(); Map<String, Object> map = new HashMap<>(); map.put("status",200); map.put("msg",authentication.getPrincipal()); //authentication.getPrincipal() 就是登录成功的用户信息 out.write(new ObjectMapper().writeValueAsString(map)); //这是写出去的 转成json串 out.flush(); out.close(); } }) //这个是登录失败的一个处理器,与上面类似。比如登录失败,服务端要跳到哪个页面去 .failureHandler(new AuthenticationFailureHandler() { @Override //这边只有异常,异常可以锁定出错的问题 public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException { resp.setContentType("application/json;chartset=utf-8"); //设置要返回的json格式 PrintWriter out = resp.getWriter(); Map<String, Object> map = new HashMap<>(); map.put("status",401); if(e instanceof LockedException){ //nstanceof 运算符是用来在运行时指出对象是否是特定类的一个实例 map.put("msg","账户被锁定,登录失败!"); }else if (e instanceof BadCredentialsException){ map.put("msg","用户名或密码错误,登录失败!"); }else if (e instanceof DisabledException){ map.put("msg","账户被禁用,登录失败!"); }else if (e instanceof AccountExpiredException){ map.put("msg","账户过期,登录失败!"); }else if (e instanceof CredentialsExpiredException){ map.put("msg","密码过期,登录失败!"); }else { map.put("msg","登录失败!"); } out.write(new ObjectMapper().writeValueAsString(map)); //这是写出去的 转成json串 out.flush(); out.close(); } }) .permitAll() //这个表示和登录相关的接口 直接就可以访问。 permit 英文是 许可的意思 .and() //这边配置注销登录配置 .logout() .logoutUrl("/logout") //这是注销登录的url //这是注销登录成功的一个处理方法,返回前台json数据 .logoutSuccessHandler(new LogoutSuccessHandler() { @Override public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException { resp.setContentType("application/json;chartset=utf-8"); //设置要返回的json格式 PrintWriter out = resp.getWriter(); Map<String, Object> map = new HashMap<>(); map.put("status",200); map.put("msg","注销登录成功"); //authentication.getPrincipal() 就是登录成功的用户信息 out.write(new ObjectMapper().writeValueAsString(map)); //这是写出去的 转成json串 out.flush(); out.close(); } }) .and() .csrf().disable(); //这边表示 关闭 csrf攻击(跨站请求伪造) 为了防止测试时报错 } }
HttpSecurity的配置以及登录表单的详细配置和注销登录的配置
最新推荐文章于 2024-06-12 09:40:39 发布