SpringBoot+SpringSecurity+Jwt权限认证---认证

 1. 整体逻辑

1. SpringSecurity认证的逻辑规则

启动项目时,SpringBoot自动检索所有带@Configuration的注解,所以就将我们的WebSecurityConfig给加载了,这个config中,我们需要在configure(AuthenticationManagerBuilder auth)方法中注册一个继承自UserDetailsService的接口,这个接口中只有一个方法,那就是使用username获取到数据库中用户信息并返回成UserDetail实体。这个方法需要我们按照我们的不同业务场景重写

WebSecurityConfig


/**
 * @description:
 * @author: coderymy
 * @create: 2020-10-01 13:54
 * <p>
 * 1\. 创建WebSecurityConfig 类继承WebSecurityConfigurerAdapter
 * 2\. 类上加上@EnableWebSecurity,注解中包括@Configuration注解
 * <p>
 * WebSecurityConfigurerAdapter声明了一些默认的安全特性
 * (1)验证所有的请求
 * (2)可以使用springSecurity默认的表单页面进行验证登录
 * (3)允许用户使用http请求进行验证
 */

/**
 * 如何自定义认证
 * 1\. 实现并重写configure(HttpSecurity http)方法,鉴权,也就是判断该用户是否有访问该api的权限
 * <p>
 * <p>
 * 页面显示403错误,表示该用户授权失败(401代表该用户认证失败)前端可以使用返回的状态码来标识如何给用户展示
 * 用2XX表示本次操作成功,用4XX表示是客户端导致的失败,用5XX表示是服务器引起的错误
 */
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    public static void main(String[] args) {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode("123");
        System.out.println(encode);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        AuthenticationManager manager = super.authenticationManagerBean();
        return manager;
    }

    /**
     * SpringSecurity5.X要求必须指定密码加密方式,否则会在请求认证的时候报错
     * 同样的,如果指定了加密方式,就必须您的密码在数据库中存储的是加密后的,才能比对成功
     *
     * @return
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //鉴权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /**
         * 1\. HttpSecurity被声明为链式调用
         * 其中配置方法包括
         *  1\. authorizeRequests()url拦截配置
         *  2\. formLogin()表单验证
         *  3\. httpBasic()表单验证
         *  4\. csrf()提供的跨站请求伪造防护功能
         */
        /**
         * 2\. authorizeRequests目的是指定url进行拦截的,也就是默认这个url是“/”也就是所有的
         * anyanyRequest()、antMatchers()和regexMatchers()三种方法来拼配系统的url。并指定安全策略
         */
        http.authorizeRequests()
                //这里指定什么样的接口地址的请求,需要什么样的权限 ANT模式的URL匹配器
                .antMatchers("/select/**").hasRole("USER")//用户可以有查询权限
                .antMatchers("/insert/**").hasRole("ADMIN")//管理员可以有插入权限权限
                .antMatchers("/empower/**").hasRole("SUPERADMIN")//超级管理员才有赋权的权限
                .antMatchers("/login/**").permitAll()//标识list所有权限都可以直接访问,即使不登录也可以访问。一般将login页面放给这个权限
                .and()
                .formLogin()
//                .loginProcessingUrl("/login/user")//用来定义什么样的API请求时login请求
//                .permitAll()//login请求需要是所有权限都可以的
                .and().csrf().disable();

        /**
         * 将自定义的JWT过滤器加入configure中
         */
        JWTAuthenticationFilter jwtAuthenticationFilter = new JWTAuthenticationFilter(this.authenticationManager());
        http.addFilterBefore(jwtAuthenticationFilter, JWTAuthenticationFilter.class);
    }

    @Autowired
    private MyUserDetailsService myUserDetailsService;

    //认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService);
    }

}

MyUserDetailsService


@Service
public class MyUserDetailsService implements UserDetailsService {

    @Resource
    private UsersRepository usersRepository;

    /**
     * 其实这样就完成了认证的过程,能获取到数据库中配置的用户信息
     *
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //获取该用户的信息
        Users user = usersRepository.findByUsername(username);

        if (user == null) {//用户不存在报错
            throw new UsernameNotFoundException("用户不存在");
        }

        /**
         * 将roles信息转换成SpringSecurity内部的形式,即Authorities
         * commaSeparatedStringToAuthorityList可以将使用,隔开的角色列表切割出来并赋值List
         * 如果不行的话,也可以自己实现这个方法,只要拆分出来就可以了
         */
        //注意,这里放入Authorities中的信息,都需要是以Role_开头的,所以我们在数据库中配置的都是这种格式的。当我们使用hasRole做比对的时候,必须要是带Role_开头的。否则可以使用hasAuthority方法做比对
        user.setAuthorities(AuthorityUtils.commaSeparatedStringToAuthorityList(user.getRoles()));

        return user;
    }
}

其实如果去掉上面的将自定义的JWT过滤器加入到过滤链中的话,这个认证过程已经完成了。使用下面的代码就可以调用起整个认证程序。

核心代码

authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userDto.getUsername(), userDto.getPassword()));

这一行就会将username和password放到认证程序中进行认证。

也就是需要我们自己也逻辑让他去触发这个代码的实现。就可以自动完成认证程序了。就会触发使用username获取到数据库用户信息,然后经过密码加密比对之后会将认证结果返回。

我们整合JWT其实也很简单,其实就是将JWT的登录部分的操作,使用过滤器封装,将该过滤器放到整个认证的过滤链中

2. 自定义JWT过滤器的配置

SpringSecurity过滤器的配置无非以下几个条件

  1. 该过滤器过滤什么样的API请求(也就是说什么样的API请求会触发该过滤器执行)。配置被过滤的请求API
  2. 该过滤器做什么事
  3. 该过滤器执行成功以及执行失败的各种情况该怎么做
  4. 该过滤器执行的时机是什么样的,也就是在过滤链之前还是之后执行

先解决逻辑上以上三个问题的答案

  1. 我们需要拦截认证请求,肯定是形如xxx/login/xxx这种API接口的请求啦
  2. 这个过滤器会做什么事呢?
    1. 首先,我们需要进行用户名密码的基础验证,也就是合不合法
    2. 我们需要
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值