SpringBoot 整合Security 登陆页面,用户认证,成功失处理

Spring Security

文章目录

  • Spring Security
  • 整合入项目
    • form 与basic 认证
    • 拦截器部分
  • 自定义用户认证
    • 实现
    • 修改自定义的登录页面
    • 实现一个跳回登陆页面的请求路径
      • 配置类
      • 请求url /skip编写
  • 认证成功失败的处理
    • 失败逻辑
  • 底部

整合入项目

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-securityartifactId>
dependency>

启动项目后 初始账户user 密码在控制台

Using generated security password: 8a09e79b-5b22-41bf-a211-2226280f6345

form 与basic 认证

@Configuration
public class SecurityConfig  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.httpBasic()
                .and()
                .authorizeRequests()//授权配置
                .anyRequest()   //所有请求
                .authenticated();   //都需要认证

        //http.formLogin() // 表单方式
        //        .and()
        //        .authorizeRequests() // 授权配置
        //        .anyRequest()  // 所有请求
        //        .authenticated(); // 都需要认证
    }
}

SpringBoot 整合Security 登陆页面,用户认证,成功失处理_第1张图片

拦截器部分

拦截链 功能
UsernamePasswordAuthenticationFilter 处理基于表单方式的登录认证
BasicAuthenticationFilter 处理HTTPbasic 方式登录
FilterSecurityInterceptor 判断当前身份认证是否成功,是否有相应的权限认证失败抛出异常
ExceptionTranslateFilter 捕获认证失败的异常,返回认证失败重定向的页面、或者权限不足的相应信息

自定义用户认证

主要内容 org.springframework.security.core

自定义UserDetails,或者用 自带的接口实现类

// 源码
public interface UserDetailsService {
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
//保存用户信息的 对象
public interface UserDetails extends Serializable {
    //获取用户包含的权限,
    Collection<? extends GrantedAuthority> getAuthorities();

    // 用户密码账户, 一开始会是名为的方式
    String getPassword();
    String getUsername();

    // 账户是否过期
    boolean isAccountNonExpired();

    //账户是否锁定
    boolean isAccountNonLocked();

    // 账户密码是否过期
    boolean isCredentialsNonExpired();

    //账户是否可用
    boolean isEnabled();
}

实现

实现 UserDetailsService

//自定义用户 详情
@Configuration
public class UserDetailService  implements UserDetailsService {

    //在 security 配置类中 注入BCryptPasswordEncoder
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // MyUser 模拟数据库
        MyUser user = new MyUser();
        user.setUserName(username);
        user.setPassword(passwordEncoder.encode("123456"));
        // 输出加密密码
        System.out.println(user.getPassword());

        //返回 security 建权好的对象
        return new User(username, user.getPassword(), user.isEnabled(),
                user.isAccountNonExpired(), user.isCredentialsNonExpired(),
                user.isAccountNonLocked(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

// 默认配置类
@Configuration
public class SecurityConfig  extends WebSecurityConfigurerAdapter {

    //手动注入 密码加密到 ioc 容器中
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder() ;
    }
}

修改自定义的登录页面

**注意:**当 loginPage 指定了跳转登陆页面的URL 后,.antMatchers(“/login.html”).permitAll() 来设置不被拦截。不然会死循环

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.formLogin() // 表单登录
      
            .loginPage("/login.html") 
            .loginProcessingUrl("/login")//处理表单登陆的url
      
            .and()
            .authorizeRequests() // 授权配置
            .antMatchers("/login.html").permitAll()
            .anyRequest()  // 所有请求
            .authenticated(); // 都需要认证
     				.and().csrf().disable();
}

实现一个跳回登陆页面的请求路径

配置类

@Configuration
public class LoginSecurityConfig extends WebSecurityConfigurerAdapter   {
    //手动注入 密码加密到 ioc 容器中
    @Bean
    public PasswordEncoder passwordEncoder(){       return new BCryptPasswordEncoder() ;    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage("/skip") //处理跳转的url
                .loginProcessingUrl("/login")  //处理登陆的url

                .and()
                .authorizeRequests()//授权配置
                .antMatchers("/login.html","/skip").permitAll() //匹配路径,不做权限认证
                .anyRequest()   //所有请求
                .authenticated()   //都需要认证
                .and().csrf().disable();
    }
}

请求url /skip编写

@RestController
public class BrowserSecurityController {

    // security 提供的 缓存请求的对象
    private RequestCache requesrtCache = new HttpSessionRequestCache();
    // security 提供的 重定向的方法
    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @GetMapping("sikp")
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public String sikpAuthenticaiton(HttpServletRequest req, HttpServletResponse resp)throws IOException {
        //获取本次请求额 http 信息
        SavedRequest savedRequest = requesrtCache.getRequest(req, resp);
        if (savedRequest != null) {
            String targetUrl = savedRequest.getRedirectUrl();
            // 请求是 .html 结尾 就是重定向 到登陆页面
            if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")) {
                redirectStrategy.sendRedirect(req,resp,"/login.html");
            }
        }
        return "访问的资源需要身份认证";
    }
}

localhost:8080/hello 重定向到 http://localhost:8080/skip

http://localhost:8080/login.html 重定向到表单登陆

**注意: security 的拦截器是实现接口方法后会自动调用 WebSecurityConfigurerAdapter
在练习的时候,多个配置文件记得注释掉 其他的接口,我一开始只注释了@Config 导致多个拦截器冲突,后写的一直不生效!!!**

认证成功失败的处理

AuthenticationSuccessHandler 主要实现接口
在到配置类中配置

@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    @Autowired
    private ObjectMapper mapper; //jackson 工具
    
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {
        //编写成功登陆 的业务逻辑
        //这里面 给前端返回一个 json 数据
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(mapper.writeValueAsString(authentication));
        System.out.println("登陆成功");
    }
}
    @Autowired
    public MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage("/skip") //处理跳转的url
                .loginProcessingUrl("/login")  //处理登陆的url

                .successHandler(myAuthenticationSuccessHandler)
          ......

SpringBoot 整合Security 登陆页面,用户认证,成功失处理_第2张图片

常见业务如请求重定向

    // 请求信息 , 转发工具
    private RequestCache requestCache = new HttpSessionRequestCache();
    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

        SavedRequest savedRequest = requestCache.getRequest(request, response);
        redirectStrategy.sendRedirect(request, response, "目标页面");

失败逻辑

步骤同上 实现AuthenticationSuccessHandler 只是在配置文件配置

.failureHandler()
失败异常对应接口 AuthenticationException

底部

你可能感兴趣的:(spring,secuitry,spring)