Shiro 简单的安全框架配置

116 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情

前言

在这个互联网日益壮大的时代,网络安全成为了必不可少的一门功课心法,如果一个网站连安全也不到,那这个网站在公网根本站不住脚,我曾经有个项目就是数据库安全没有做好,被黑客使用最最最最简单的ipv4for循环大法,直接暴力连接数据库导致数据库劫持事件,这还好当时企业没有放入数据还在开发按阶段,要是生产阶段那直接赔钱走人。由此可知安全是首当其冲排在第一的。

shiro web安全权限框架

在java web中的安全我们有许多中解决办法,第一种就是自己手写权限校验即可,第二种是采取spring security框架进行校验,第三种则是我们今天的主角shiro框架。

讲到shiro人们经常跟security进行对比比较,但是我觉得完全没必要,因为shiro是轻量级的安全框架,在某些方面是你security比不了的,但是也不能踩一捧一,security强大之处也是shiro比较不了的。我个人认为他们的作用面不同,security为企业sass进行更强大的赋能,支持高度自定义,支持最新ouath2,支持插件插拔。而shiro则是给小企业单体项目进行更快速的敏捷开发,shiro的快速创建完全就config类一扔,realm类复写一下认证与授权方法,定义一下Map拦截注册,好,搞定,你就拥有了一个小体量的权限校验。而这时候security还在配置类玩呢。

shiro 快速配置例子

@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

    //设置安全管理器
    shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

    //添加shir的内置过滤器
    /*
    anon: 无需认证就可以访问
    authc: 必须认证了才能访问
    user: 必须拥有记住我 功能才能用
    perms: 拥有对某个资源的权限才能访问
    role: 拥有某个角色权限才能访问
    */
    Map<String, String> ruleMap = new LinkedHashMap<>();

    //这里注意先授权,在认证,顺序写反会失效
    //授权
    ruleMap.put("/user/r1", "perms[adminmouth]");
    ruleMap.put("/user/r2", "perms[user]");

    //给rulemap put值就可以
    //拦截
    ruleMap.put("/login", "anon");
    ruleMap.put("/logout", "logout");
    ruleMap.put("/**", "authc");


    shiroFilterFactoryBean.setFilterChainDefinitionMap(ruleMap); //对上面规则做拦截

    //设置登录的请求,没有认证就跳到这个请求
    shiroFilterFactoryBean.setLoginUrl("/tologin");
    //未授权请求
    shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");


    return shiroFilterFactoryBean;
}


//defaultWEbSecuritymanager
@Bean
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    //关联userRealm
    securityManager.setRealm(userRealm);
    return securityManager;
}

这个AuthorizingRealm 主要做认证和授权,是shiro的关键核心


//自定义UserRealm
public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserMapper userMapper;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        System.out.println("执行了授权");

        //在这里可以 从数据库拿到授权,然后写到simpleAuthorizationInfo里面,从而实现不同用户不同权限


        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();


        simpleAuthorizationInfo.addStringPermission("adminmouth"); //加s 就是放数组多个权限

        return simpleAuthorizationInfo;
    }

    //认证, 在这里做校验
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

        if (StringUtils.isEmpty(authenticationToken.getPrincipal())) {
            return null;
        }
        System.out.println("执行了认证");

        //获得前端传来的用户名
        String username = authenticationToken.getPrincipal().toString();
        String password = new String(token.getPassword());
        if (username == null) {
            return null;
        }


        //用户名,密码 数据库中取
        User user = userMapper.selcetByUser(username);
        String passwordInDB = user.getPassword();
        String passwordEncoded = new SimpleHash("md5", password, "mouth", 2).toString();

        //根据用户名查询数据库是否有这个人
        if (user == null || !passwordEncoded.equals(passwordInDB)) {
            return null;
        }


        //密码认证,把密码丢给shiro做认证
        return new SimpleAuthenticationInfo(username, password, "");
    }
}