首页 > 编程语言 > 详细

SpringBoot+Mybatis+PostMan(十):用户角色权限访问控制三(禁用session、启用token并集成redis)

时间:2021-02-03 12:12:40      阅读:106      评论:0      收藏:0      [点我收藏+]

在上一篇文章中,对于用户角色权限访问控制实现,我们利用了spring boot Security自带的session的cookie串接起访问整个过程,进而实现角色访问控制 , 这次,我们进行进一步的探讨,舍弃springBoot Security自带session,转而自定义生成token,将token存储于redis,进而实现通过redis中的token串联起整个过程,这是我们现在的整体思路,接下来就对此部分的实现进行讲解。准备工作上一篇文章已经写好了,现在我们直接进入正题。

一、正题

1. 在上一篇文章的基础上,我们要添加一个JWTAuthorizationFilter过滤类,用于判断用户是否是第一次登陆(通过token进行判定)

/**
 * @author yeyuting
 * @create 2021/1/29
 */
//验证成功后开始鉴权
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

    @Autowired
    JedisUtil jedisUtil ;

    public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {

        String tokenHeader = request.getHeader(JwtTokenUtils.TOKEN_HEADER);
        //String roleHeader = request.getHeader(JwtTokenUtils.ROLE_HEADER) ;
        // 如果请求头中没有Authorization信息则直接放行了
        if (tokenHeader == null) {
            super.doFilterInternal(request, response, chain);
            return;
        }
        // 如果请求头中有token,则进行解析,并且设置认证信息  ???
        SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader));
        super.doFilterInternal(request, response, chain);
    }

    // 从token中获取用户信息
    private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader) {
        String token = tokenHeader.replace(JwtTokenUtils.TOKEN_PREFIX, "");

        //去redis里面拿token 确认redis中存在和token对应的值
       Jedis jedis = new Jedis("localhost" , 6379) ;
       String username = jedis.get(token) ;

        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(jedis.get(JwtTokenUtils.ROLE_HEADER));
        grantedAuthorities.add(grantedAuthority) ;
        if (username != null){
            return new UsernamePasswordAuthenticationToken(username, null, grantedAuthorities);
        }
        return null;
    }
}

2. 接着实现JwtTokenUtils类,用于存储前端头信息。

/**
 * @author yeyuting
 * @create 2021/1/29
 */
public class JwtTokenUtils {

    public static final String TOKEN_HEADER = "token";
    public static final String ROLE_HEADER = "authority";
    public static final String TOKEN_PREFIX = "Bearer";


}

3. webConfig类禁用session

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        object.setSecurityMetadataSource(cfisms());
                        object.setAccessDecisionManager(cadm());
                        return object ;
                    }
                })
                .antMatchers("/userLogin").permitAll()
                // 所有访问该应用的http请求都要通过身份认证才可以访问
                .anyRequest().authenticated()
                .and().httpBasic()
                .and()
                .csrf().disable()
                // 指定登陆URL
                .formLogin()
                .loginProcessingUrl("/userLogin")
                .successHandler(customAuthenticationSuccessHandler)
                .failureHandler(customAuthenticationFailureHandler)
                .and()
                .exceptionHandling().accessDeniedHandler(authenticationAccessDeniedHandler)
                .authenticationEntryPoint(simpleAuthenticationEntryPoint)
                .and()
                .addFilter(new JWTAuthorizationFilter(authenticationManager()))
                // 不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

4. UserServiceImpl类loadUserByUsername方法实现token生成和存入redis:

@Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //角色和权限共用GrantedAuthority接口,后面采集到的角色信息将存储到grantedAuthorities集合中
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        //将前端传过来的username信息传入数据库比对,将匹配的用户信息存入user对象
        User user = userMapper.selectByName1(username) ;

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


        //根据用户id进入user_role表中查询对应的角色id,存储到userRoles列表中
        List<UserRole> userRoles = userRoleMapper.selectList(user.getId()) ;
        //遍历userRoles集合
        for (UserRole ur : userRoles){
            //再根据用户id查到对应的role,此时就拿到了用户对应的角色
            Role role = roleMapper.selectOne1(ur.getRoleId());
            //将对应的角色存储到权限grantedAuthorities集合中
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getRole());
            grantedAuthorities.add(grantedAuthority);
        }
        //生成token
        //将原有的token值全部干掉,防止重复登陆
        Jedis jedis = jedisUtil.getResource();
        //存入键值对
        String jedisKey = jedis.get(user.getUserName()) ;
        if(jedisKey != null){
            jedisUtil.delString(user.getUserName());
        }

        String token = tokenUtil.generateToken(user) ;
        user.setToken(token);
        user.setGrantedAuthority("authority");
        user.setGrantedAuthorities(grantedAuthorities);
        jedisUtil.tokenToJedis(user);
        jedis.close();
        //测试数据
        String name = user.getUserName() ;
        //创建一个用户,用于判断权限,请注意此用户名和方法参数中的username一致;BCryptPasswordEncoder是用来演示加密使用。
        //            //这里主要是实现用户名和密码的核对,如果信息都正确才给开这个权限,这是一种安全策略
        return new org.springframework.security.core.userdetails.User
                ("user",
                        new BCryptPasswordEncoder().encode(user.getPassword()), grantedAuthorities);


    }

这样一来,代码逻辑就实现了,接下来前端模拟实现。

二、前端实现

1. 用户登陆认证 实现token生成和当前登陆所需用户角色。

技术分享图片

 redis记录token和对应的角色信息。

技术分享图片

 

 2. 接着来访问selectStartIndexAndPageSize接口,第一次登陆时候逻辑上会提示用户进行登陆。

技术分享图片

 

 紧接着将token值给到接口头信息中,继续测试,发现这时候顺利访问到数据库,并将方法顺利实现,这是因为我们之前在数据库中将此接口交给了普通用户角色,所以这样一来,自然就能实现访问,这就实现了整个过程 。 

技术分享图片

 

 这便是整个token结合redis控制用户角色整个过程。

至此,结束。

SpringBoot+Mybatis+PostMan(十):用户角色权限访问控制三(禁用session、启用token并集成redis)

原文:https://www.cnblogs.com/yeyuting/p/14365922.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!