springboot2.x整合shiro+JWT实现token登录

文章目录

  • 1.参考项目和我的项目地址
    • 1.1它的不足之处
    • 2. 进行系统化改造
    • 2.1 针对《shiro不是盐值加密登录》改造
    • 2.2 对《login接口需要权限才能访问》进行改造
      • 2.3 如果用shiro缓存权限,会有下面的问题:
      • 4. shiroConfig中@Value加载失败的解决方案
        • 5. 设置redisShiro自定义ValueSerializer

1.参考项目和我的项目地址

参考demo地址:github


我的项目地址:github


注意:我的项目是
基于springboot2.x
shiro1.4.1
jwt
dubbo
zookeper
mybatisPlus3.x
mysql8.0
搭建的多模块项目

1.1它的不足之处

顺序 不足 解决方案
1 shiro不是盐值加密登录 盐值登录
2 login接口需要权限才能访问 shiroConfig添加免登录过滤
3 没有真正的角色和权限 ,只是单纯的模拟 添加数据库关于角色和权限的表

2. 进行系统化改造

2.1 针对《shiro不是盐值加密登录》改造

原本的代码

@PostMapping("/login")
 public ResponseBean login(@RequestParam("username") String username,
                           @RequestParam("password") String password) {
     UserBean userBean = userService.getUser(username);
     if (userBean.getPassword().equals(password)) {
         return new ResponseBean(200, "Login success", JWTUtil.sign(username, password));
     } else {
         throw new UnauthorizedException();
     }
 }

增加shiro盐值加密后的代码:

@PostMapping("/login")
public ResultInfo login(@RequestParam("username") String username,
                        @RequestParam("password") String password) {
    SysUser userBean = userService.findUserInfo(username);
    String encodePassword = ShiroKit.md5(password, password);
    if (userBean.getPassWord().equals(encodePassword)) {
        return new ResultInfo("200", "Login success", JWTUtil.sign(username, encodePassword));
    } else {
        throw new UnauthorizedException();
    }
}

所用到的盐值加密的工具类,注意我的代码里面其实不存储盐值,用户名就是盐值,当然你也可以把盐值换一下

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;

import java.util.Random;

/**
 * shiro工具类
 */
public class ShiroKit {



    /**
     * 加盐参数
     */
    public final static String hashAlgorithmName = "MD5";

    /**
     * 循环次数
     */
    public final static int hashIterations = 10;

    /**
     * shiro密码加密工具类
     *
     * @param credentials 密码
     * @param saltSource 密码盐
     * @return
     */
    public static String md5(String credentials, String saltSource) {
        ByteSource salt = new Md5Hash(saltSource);
        return new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations).toString();
    }


    public static void main(String[] args) {
        System.out.println(md5("xiyou","xiyou"));
    }
}

2.2 对《login接口需要权限才能访问》进行改造

其实就是在下面的代码里添加一句即可

 filterRuleMap.put("/login", "anon");

添加后变为:

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean factory(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();

        // 添加自己的过滤器并且取名为jwt
        Map<String, Filter> filterMap = new HashMap<>();
        filterMap.put("jwt", new JWTFilter());
        factoryBean.setFilters(filterMap);

        factoryBean.setSecurityManager(securityManager);
        factoryBean.setUnauthorizedUrl("/401");

        /*
         * 自定义url规则
         * http://shiro.apache.org/web.html#urls-
         */
        Map<String, String> filterRuleMap = new HashMap<>();
        // 所有请求通过我们自己的JWT Filter
        filterRuleMap.put("/**", "jwt");
        // 访问401和404页面不通过我们的Filter
        filterRuleMap.put("/401", "anon");
        filterRuleMap.put("/login", "anon");
        factoryBean.setFilterChainDefinitionMap(filterRuleMap);
        return factoryBean;
    }

2.3 如果用shiro缓存权限,会有下面的问题:

Default value is “id”, that means your principal object has a method called “getId()”
解决方案: redisCacheManager.setPrincipalIdFieldName("userName");

如果你是用用户的name登录的话
   String userName = (String) token.getPrincipal();



    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        return redisManager;
    }

    public RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        redisCacheManager.setPrincipalIdFieldName("userName");
        return redisCacheManager;
    }

4. shiroConfig中@Value加载失败的解决方案

    /**
     * lifecycleBeanPostProcessor是负责生命周期的 , 初始化和销毁的类
     * (可选)
     */
    @Bean("lifecycleBeanPostProcessor")
    public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

5. 设置redisShiro自定义ValueSerializer

因为默认的是JDK序列化乱码,虽然不影响使用,但乱码
shiro+redis的官网

你可能感兴趣的:(SpringBoot,github项目)