SpringBoot整合Shiro权限框架

本文介绍了如何在SpringBoot项目中集成Shiro权限框架,包括添加依赖、配置Realm、安全策略和登录接口实现,以完成基本的用户认证和授权功能。

前言

在系统管理中,权限是非常重要的一个环节。目前权限框架中使用比较多的有Shiro、Spring Security。🎃
本篇简单写一下SpringBoot整合Shiro权限框架小栗子🌰。

个人博客地址:SpringBoot整合Shiro权限框架

介绍Shiro

Apache Shiro 是一个强大易用的 Java 安全框架,提供了认证、授权、加密和会话管理等功能,对于任何一个应用程序,Shiro 都可以提供全面的安全管理服务。并且相对于其他安全框架,Shiro 要简单的多。++更多详细介绍参考:w3cschool-shiro++

🚀开始

创建项目就不多嗦了,直接上干货~~

相关依赖

<!-- web依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <!-- 剔除spring logging依赖,防止与log4j2冲突 -->
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- log4j依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- shiro 安全框架-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.6.0</version>
</dependency>

系统配置

shiro权限的主要配置部分分为:

  • subject(可以认为是一个认证对象,与当前应用交互的任何东西都是subject)
  • securityManager(安全管理器,所有安全相关的东西都是跟它交互的,它管理着所有的subject)
  • realm(可以认为是一个安全信息数据源,主要通过校验subject是否符合安全策略。所以我们在使用shiro时,需要先配置自己的realm)。

配置Realm

话不多说上代码~ 这里先以登录认证作为粟子

@Slf4j
public class MyShiroRealm extends AuthorizingRealm {

    @Resource
    private SysUserService sysUserService;

    /**
     * 授权信息配置
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

	// 主要以登录认证作为例子, 此处暂时不做认证, 之后例子做补充
        return null;
    }

    /**
     * 登录认证信息
     * @param token token
     * @return 认证信息
     * @throws AuthenticationException e
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 返回认证信息, 一般为用户名
        Object principal = token.getPrincipal();
        if (ObjectUtil.isNull(principal)) {
            return null;
        }
        // 获取数据库中用户信息
        String loginName = principal.toString();
        SysUser user = sysUserService.findSysUserByName(loginName);
        if (null == user) {
            log.debug("{} - 登录用户不存在!", loginName);
            throw new UnknownAccountException("登录用户不存在!");
        }

        // 使用盐加密 构造方法
        ByteSource credentialsSalt = ByteSource.Util.bytes(loginName);;
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getLoginPwd(), credentialsSalt, getName());

        // 验证信息
        //SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getLoginPwd(), getName());
        log.debug("验证登录信息: {} ===>>>> {}", loginName, simpleAuthenticationInfo.getPrincipals());
        return simpleAuthenticationInfo;
    }
}

配置安全策略

增加完Realm域配置,我们需要让此配置生效,所以需要将它添加给Shiro的安全管理策略。

/**
 * 自定义安全管理策略
 */
@Bean
public SecurityManager securityManager(MyShiroRealm myShiroRealm) {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    // 设置自定义的realm
    securityManager.setRealm(myShiroRealm);
    return securityManager;
}
/**
 * 地址过滤器
 *
 * @param securityManager
 * @return
 */
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    // 设置安全管理
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    // 设置登录地址
    shiroFilterFactoryBean.setLoginUrl("/login");
    // 设置主页地址
    shiroFilterFactoryBean.setSuccessUrl("/index");
    // 设置未授权的url
    shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
    // 开放登录接口
    filterChainDefinitionMap.put("/doLogin", "anon");
    // 生成验证码接口
    filterChainDefinitionMap.put("/captcha/captchaImg", "anon");
    // 开放静态资源文件
    filterChainDefinitionMap.put("/assets/**", "anon");
    // 其余url全部拦截,必须放在最后
    filterChainDefinitionMap.put("/**", "authc");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;
}

/**
 * shiro生命周期
 * @return
 */
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
}

/**
 * shiro注解启用配置
 * @return
 */
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
    return defaultAdvisorAutoProxyCreator;
}

/**
 *
 * @param securityManager
 * @return
 */
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor sourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    sourceAdvisor.setSecurityManager(securityManager);
    return sourceAdvisor;
}

登录

设置完自定义域,以及自定义策略我们shiro就可以进行下一步了,那就是接口认证操作,这里简单定义一个接口

/**
 * 登录操作
 *
 * @param loginName 登录名
 * @param loginPwd  登录密码
 * @return url
 */
@ResponseBody
@PostMapping("/doLogin")
public Result<String> doLogin(String loginName, String loginPwd, String captcha, boolean rememberMe, HttpServletRequest request) {

    // 验证码校验
    String sessionCaptcha = (String) request.getSession().getAttribute(AppConstants.CAPTCHA_KEY);
    if (!StringUtils.equalsIgnoreCase(captcha, sessionCaptcha)) {
        return Result.error("验证码不匹配!");
    }
    UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(loginName, loginPwd, rememberMe);
    Subject subject = SecurityUtils.getSubject();
    try {
	// 认证操作
        subject.login(usernamePasswordToken);

        // 获取登录的用户
        SysUser user = (SysUser) subject.getPrincipal();

        // 将用户信息存入cookie中
        Session session = subject.getSession();
        session.setAttribute("user", user);
        // 删除session验证码
       request.getSession().removeAttribute(AppConstants.CAPTCHA_KEY);
    } catch (UnknownAccountException e) {
        log.debug("未知用户! {}", e.getMessage());
        return Result.error("未知用户!");
    } catch (IncorrectCredentialsException e) {
        log.debug("{} - 用户登录密码校验异常! {}", loginName, e.getMessage());
        return Result.error("密码校验异常!");
    } catch (AuthenticationException e) {
        log.debug("{} - 用户登录认证失败! {}", loginName, e.getMessage());
        return Result.error("登录失败!");
    } catch (Exception e) {
        log.debug("{} - 用户登录异常! {}", loginName, e.getMessage());
        return Result.error("登录异常!");
    }
    return Result.success("登录成功!");
}

测试

接口定义完,我们需要一个登录页面来完成登录认证操作,这里使用我之前写的登录页面来完成。
在这里插入图片描述

点击登录后观察接口执行情况:
在这里插入图片描述
当执行到subject.login()方法后,会进行认证操作,这时候就会执行到我们设置的自定义Realm。红框处是我们做完登录用户与数据库中比对过后,将用户信息存到了认证信息中并返回给接口。
在这里插入图片描述

最后页面成功跳转至新页面,我们就完成了登录认证操作啦。🕛

END

简单的完成了一个登录认证的操作,之后会慢慢更新shiro的其他功能😀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

丶Yann

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值