学习记录-SpringBoot整合Shiro

125 阅读2分钟

必看

本文为作者自己的学习记录,仅供参考,切勿直接粘贴使用

1. 引入Shiro依赖

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-web-starter</artifactId>
    <version>1.13.0</version>
</dependency>

2.Shiro配置文件

  1. myUserRealm 自定义的realme ,里面就是登录的规则,要从数据库中拿到数据价格shiro
  2. securityManager 核心方法,自定义的realme要在这个注册才会生效
  3. shiroFilter 配置白名单 anon 放行; authc 拦截
@Configuration
public class ShiroConfiguration {

    @Resource
    private ShiroProperties properties;

    @Bean
    public MyUserRealm myUserRealm(HashedCredentialsMatcher hashedCredentialsMatcher) {
        MyUserRealm myUserRealm = new MyUserRealm();
        //注册加密的算法
        myUserRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        return myUserRealm;
    }

    @Bean
    public DefaultWebSecurityManager securityManager(MyUserRealm myUserRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myUserRealm);
        return securityManager;
    }

    /**
     * 白名单
     */
    @Bean
    public ShiroFilterChainDefinition shiroFilter() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
        properties.getList().forEach(path -> definition.addPathDefinition(path, "anon"));
        definition.addPathDefinition("/**", "authc");
        return definition;
    }

    /**
     * @function 告诉shiro 密码的加密算法 ,还要在自定义realm中注册
     * @Time 2024/4/30 17:24
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        //加密算法 更加密工具类保持一致
        matcher.setHashAlgorithmName(Md5Hash.ALGORITHM_NAME);
        //加密次数
        matcher.setHashIterations(ShiroUtils.HASH_ITERATIONS);
        return matcher;
    }
}

3.定义properties类和yml

propertice 中定义了一个List用来接收白名单的路径 yml中就是基本配置

@Data
@Component
@ConfigurationProperties("shiro.white")
public class ShiroProperties {
    private List<String> list;
}
# shiro配置
shiro:
  white:
    list:
      - "/member/login"
      - "/member/register"
      - "/member/un/auth" #失败
      - "/druid/*"
      # 放行 v3  swagger
      - "/swagger**/**"
      - "/webjars/**"
      - "/doc.html"
      - "/v3/**"
  loginUrl: "/member/un/auth"

4.自定义Realm

public class MyUserRealm extends AuthenticatingRealm {

    @Resource
    private UserShiroMapper userShiroMapper;

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();
        //判断用户名是否为空
        if (Objects.isNull(username)) {
            throw new ServiceException(ResponseCode.USER_LOGIN_ERROR);
        }
        //根据用户名查询用户信息
        User user = userShiroMapper.getUser(username);
        //用户名不存在
        if (Objects.isNull(user)) {
            throw new ServiceException(ResponseCode.USER_NAME_ERROR);
        }
        //用户已被锁定
        if (user.getUserStatus() == 1) {
            throw new ServiceException(ResponseCode.USER_LOCK_ERROR);
        }
        //返回给前端的数据
        UserVo userVo = BeanConvertUtils.convertTo(user, UserVo::new);
        //1.用户所有信息存在session 2.数据库里的用户密码 3.加密盐 4.客户端传来的用户名
        return new SimpleAuthenticationInfo(userVo, user.getUserPassword(), null, username);
    }
}

5.Shiro入口

@PostMapping("/userLogin")
public String userLogin(@RequestBody UserLoginQo userLoginQo) {
    //获取shiro的入口对象 Subject 保持当前用户对象
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userLoginQo.getUsername(), userLoginQo.getPassword());
    subject.login(usernamePasswordToken);
    subject.getPrincipal()//登录成功可以获取存入session的用户数据
    return "OK";
}