当前位置:   article > 正文

springsecurity+vue实现登陆认证_spring security+vue3登录实现

spring security+vue3登录实现

通过查看UsernamePasswordAuthenticationFilter获取用户名和密码的实现方法可以看到,默认只能获取form表单提供的数据无法获得请求体中的数据。所以,要想获得请求体中的数据,需要自定义过滤器。

这里有两种方式获得用户名和密码

  • 直接重写obtainPasswordobtainUsername
  • 查看attemptAuthentication这个方法我们可以发现,用户名和密码是在这个方法里面获得并且使用的,因此我们可以直接重写这个方法。
1、编写UserAuthenticationFilter过滤器,继承UsernamePasswordAuthenticationFilter
@Slf4j
public class UserAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    @Autowired
    private AuthenticationManager authenticationManager;
  
    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
            throws AuthenticationException {
        try {
            Employee employee = new ObjectMapper().readValue(req.getInputStream(), Employee.class);
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(employee.getUsername(), employee.getPassword()));
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
2、IEmployeeService 接口继承UserDetailsService
public interface IEmployeeService extends IService<Employee>,UserDetailsService {

}

  • 1
  • 2
  • 3
  • 4

EmployeeServiceImpl实现类
这里只需要实现loadUserByUsername方法,验证用户是否存在、是否被禁用

@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService{

    @Autowired
    EmployeeMapper employeeMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        System.out.println(employeeMapper);
        System.out.println(username);
        QueryWrapper<Employee> wrapper = new QueryWrapper<>();
        wrapper.eq("username",username);
        Employee employee = employeeMapper.selectOne(wrapper);
        UserDetails userDetail = User.withUsername(username).password(employee.getPassword()).roles(username).build();
        return userDetail;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
3、编写UserLoginAuthenticationProvider,继承DaoAuthenticationProvider

通过继承DaoAuthenticationProvider,可以自定义用户密码验证并查看异常信息。

若不实现该类,抛出的异常信息会都变成Bad credentials

@Component
public class UserLoginAuthenticationProvider extends DaoAuthenticationProvider {

    @Autowired
    private UserDetailsServiceImpl detailsService;
    @Autowired
    private PasswordEncoder encoder;

    /**
     * 找到容器中的detailsService,并执行setUserDetailsService方法,完成赋值
     *
     * 必须要给UserDetailsService赋值,否则会出现UnsatisfiedDependencyException
     */
    @Autowired
    private void setDetailsService() {
        setUserDetailsService(detailsService);
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        String presentedPassword = authentication.getCredentials().toString();
        if (!encoder.matches(presentedPassword, userDetails.getPassword())) {
            throw new BadCredentialsException(messages.getMessage("badCredentials", "用户密码错误"));
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
4、WebSecurityConfig 配置
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    IEmployeeService employeeService;

    //注入AuthenticationManager,可能存在同名bean,
    //配置文件中设置allow-bean-definition-overriding: true
    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       //使用DetailsService进行数据校验
        auth.userDetailsService(employeeService).passwordEncoder(passwordEncoder());

        //使用自定义的Provider,进行数据校验
//        auth.authenticationProvider(loginAuthenticationProvider);
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    //重要,将UserAuthenticationFilter添加到容器
    @Bean
    public UserAuthenticationFilter userAuthenticationFilter() throws Exception {
        UserAuthenticationFilter filter = new UserAuthenticationFilter();
        //设置验证成功后的回调
        filter.setAuthenticationSuccessHandler((request,response,authentication)->{

            //响应成功状态码必须为200
            response.setStatus(200);
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setCharacterEncoding("utf-8");
            //将数据以json的形式返回给前台
            response.getWriter().print(JSON.toJSONString(Result.success(null)));
        });
        //设置验证失败后的回调
        filter.setAuthenticationFailureHandler((request,  response,  exception) ->{

            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setCharacterEncoding("utf-8");
            //将数据以json的形式返回给前台
            response.getWriter().print(JSON.toJSONString(Result.error("登录失败")));

        });
        //设置用户发起登陆请求时的url
        filter.setFilterProcessesUrl("/employee/login");
        filter.setAuthenticationManager(authenticationManager());
        return filter;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()   //屏蔽跨站请求

                .authorizeRequests()
                .anyRequest().permitAll()
                .and()
                .formLogin()
//                .loginPage("employee/login")
                .loginProcessingUrl("/employee/login")
                .successForwardUrl("/success");

        http.cors(); // 开启跨域
        //添加自定义的过滤器
        http.addFilterAt(userAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
5、axios.defaults.withCredentials=true//开启携带cookies

本文参考于:http://t.zoukankan.com/xlwq-p-13411575.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/53933
推荐阅读
相关标签
  

闽ICP备14008679号