SpringSecurity集成JWT实现后端认证授权保姆级教程-授权配置篇

70 篇文章 3 订阅
58 篇文章 3 订阅

🍁 作者:知识浅谈,CSDN签约讲师,CSDN博客专家,华为云云享专家,阿里云专家博主
📌 擅长领域:全栈工程师、爬虫、ACM算法
💒 公众号:知识浅谈
🔥 微信:zsqtcyl 联系我领取福利

视频教程:SpringSecurity集成JWT实现后端认证授权保姆级教程-授权配置
完整代码:SecurityJwt
上一篇:SpringSecurity集成JWT实现后端认证授权保姆级教程-认证配置篇
🤞上一节编写了对应的SpringSecurity的认证,本节开始进行SpringSecurity授权🤞

🎈修改用户类返回用户权限信息

修改对应的getAuthorities方法
在这里插入图片描述

@TableName(value ="cust_user")
@Data
public class CustUser implements Serializable, UserDetails {  //这里新增实现UserDetails 
    @TableId(type = IdType.AUTO)
    private Integer id;
    private String username;
    private String nickname;
    private Integer enable;
    private String password;
//----------------------------------------------------以下为新增的部分---------------------------------
     @TableField(exist = false)
    private List<String> permissions;  //权限集合

    //存储SpringSecurity所需要的权限信息的集合
    //安全限制,不允许序列化
    @JSONField(serialize = false)
    @JsonIgnore
    @TableField(exist = false)
    private List<GrantedAuthority> authorities;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
//        return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
        if (this.authorities == null) {
            //把permissions中字符串类型的权限信息转换成GrantedAuthority对象存入authorities中
            this.authorities = this.permissions.stream().distinct().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
        }
        return this.authorities;
    }
    //------------------------------------------------------------------------------------------------
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return true;
    }

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}

🎈对CustUserServiceImpl 进行修改

对CustUserServiceImpl 中的loadUserByUsername进行修改

  1. 针对之前的数据准备篇的CustUserServiceImpl实现类 进行更改

    @Service
    public class CustUserServiceImpl extends ServiceImpl<CustUserMapper, CustUser> implements CustUserService{ //这个地方新增实现CustUserService接口
    
        @Autowired
        private CustUserMapper custUserMapper;
    
        @Autowired
        private SysMenuMapper menuMapper;
        //-----------------------------------------------------以下为修改的内容------------------------------------------
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            LambdaQueryWrapper<CustUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CustUser::getUsername, username);
            CustUser user = custUserMapper.selectOne(queryWrapper);
            if (user == null) {
                log.error("用户名不存在");
                throw new UsernameNotFoundException("用户名不存在");
            }else {
                List<String> permissions = menuMapper.selectPermsByUserId(user.getId());
                user.setPermissions(permissions); //封装权限
                return user;
            }
        }
    //----------------------------------------------------------------------------
    }
    

    上边的这个主要是实现loadUserByUsername方法中获取数据库中用户的权限。
    添加之后会发现上边的menuMapper.selectPermsByUserId(user.getId());报错,因为我们还没有在menuMapper新增selectPermsByUserId方法,接下来我们新增一个查询用户权限的方法。

🎈SecurityConfig配置类修改

新增JwtAuthenticationFilter 注入 并添加到addFilterBefore中

@Slf4j
@EnableWebSecurity
@Configuration
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法安全权限校验
public class SecurityConfiguration {

//----------------------------新增--------------------------------------------------
    private final JwtAuthenticationFilter jwtFilter; // 注入JwtAuthenticationFilter
//------------------------------------------------------------------------------
    private final JwtUtil jwtUtil; // 注入JwtUtil

    @Autowired
    private CustUserService custUserService;


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

    /**
     * 获取AuthenticationManager 登录验证的时候使用
     * @param authenticationConfiguration
     * @return
     * @throws Exception
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }


    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
         http.authorizeHttpRequests(
                (authz)->authz
                        .antMatchers("/user/login").permitAll() // 允许匿名用户访问login用于登录
                        .antMatchers("/user/logout").permitAll() // 允许匿名用户访问logout用于登出
                        .antMatchers("/doc.html", "/webjars/**", "/v2/api-docs", "/swagger-resources/**").permitAll() // 允许匿名用户访问swagger
//                        .antMatchers("/test").hasAuthority("test") // 拥有test权限的用户才能访问test接口
                        .anyRequest().authenticated()) // 其他请求必须经过身份验证
                .exceptionHandling(conf->conf // 异常处理
                        .authenticationEntryPoint((req, res, authException) -> { //认证异常

                            log.info("认证异常");
                            res.setContentType( "application/json;charset=utf-8" );
                            res.getWriter().write(new Gson().toJson(Result.error(401, authException.getMessage())));
                        })
                        .accessDeniedHandler((req, res, authException) -> { //权限异常
                            log.info("权限异常");
                            res.setContentType("application/json;charset=utf-8");
                            res.getWriter().write(new Gson().toJson(Result.error(403, authException.getMessage())));
                        })
                )
                .csrf(AbstractHttpConfigurer::disable) // 禁用csrf
                .sessionManagement(conf->conf.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 禁用session
                //----------------------------新增--------------------------------------------------
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)//指定过滤器
                //-----------------------------------------------------------------------------------
                .cors();
        return http.build();
    }
}

🎈新增根据用户id查询权限的方法

在mapper/SysMenuMapper中的新增方法selectPermsByUserId

public interface SysMenuMapper extends BaseMapper<SysMenu> {
    List<String> selectPermsByUserId(Integer id);
}

在resources/SysMenuMapper/xml中的新增方法selectPermsByUserId

    <select id="selectPermsByUserId" resultType="java.lang.String">
        SELECT
            DISTINCT m.`perms`
        FROM
            sys_user_role ur
                LEFT JOIN `sys_role` r ON ur.`role_id` = r.`id`
                LEFT JOIN `sys_role_menu` rm ON ur.`role_id` = rm.`role_id`
                LEFT JOIN `sys_menu` m ON m.`id` = rm.`menu_id`
        WHERE
            user_id = #{id}
          AND r.`status` = 0
          AND m.`status` = 0
    </select>

🎈编写权限测试的接口

在数据库中的增加test权限
在这里插入图片描述

@Api(tags = "测试类")
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private CustUserService custUserService;

    @ApiOperation(value = "测试方法")
    @PreAuthorize("hasAuthority('test')")  // 权限验证 需要用户具有test权限
    @GetMapping("/test")
    public CustUser test(){
        return custUserService.getById(1);
    }

}

到这授权就已经好了。如果还想根据角色进行权限认证,可自己百度,后边有时间我会更新。

🍚总结

大功告成,撒花致谢🎆🎇🌟,关注我不迷路,带你起飞带你富。
Writted By 知识浅谈

  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知识浅谈

您的支持将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值