springBoot 项目集成shiro安全框架并设置shiro的过期时间以及存储当前登陆用户

记录着玩。最近搭建了一套Spring boot的项目,所以想着搞一个安全框架,所以就搭建了一套shiro框架。

第一步:在pom文件中引入shiro的包

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.3.2</version>
        </dependency>

第二部:创建shiro的conf文件和customerRealm文件

第一个是shiroConf文件

package com.example.springboot.config;

import com.example.springboot.shiro.CustomRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }

    //将自己的验证方式加入容器
    @Bean(name = "CustomRealm")
    public CustomRealm myShiroRealm() {
        CustomRealm customRealm = new CustomRealm();
        return customRealm;
    }

    //权限管理,配置主要是Realm的管理认证
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    //Filter工厂,设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> map = new HashMap<>();
        map.put("/login","anon");
        map.put("/doc.html", "anon");
        map.put("/swagger-resources/**", "anon");
        map.put("/v2/api-docs", "anon");
        map.put("/v2/api-docs-ext", "anon");
        map.put("/webjars/**", "anon");
        map.put("/**", "authc");
//        //登录
        shiroFilterFactoryBean.setLoginUrl("/login");
//        //首页
//        shiroFilterFactoryBean.setSuccessUrl("/index");
        //错误页面,认证不通过跳转
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }


    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}

第二个是customRealm

package com.example.springboot.shiro;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.springboot.entity.UserEntity;
import com.example.springboot.service.UserService;
import com.example.springboot.utils.PasswordEncryption;
import lombok.SneakyThrows;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.Set;

public class CustomRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<String> stringSet = new HashSet<>();
        stringSet.add("user:show");
        stringSet.add("user:admin");
        info.setStringPermissions(stringSet);
        return info;
    }

    /**
     * shiro认证账号密码
     * <p>
     * 获取即将需要认证的信息
     */
    @SneakyThrows
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("-------身份认证方法--------");
        String userName = (String) authenticationToken.getPrincipal();
        String userPwd = new String((char[]) authenticationToken.getCredentials());
        //根据用户名从数据库获取密码
        UserEntity one = userService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUserName, userName));
        if (null == one)
            throw new UnknownAccountException("账号不存在");
        if (one.getStatus().equals("0"))
            throw new LockedAccountException("用户被锁定");
        if (!PasswordEncryption.authenticate(userPwd, one.getPassword(), one.getMD5()))
            throw new IncorrectCredentialsException("密码错误");

        //将用户数据存储在session中
        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute("userSession", one);
        SecurityUtils.getSubject().getSession().setTimeout(1000 * 60);//设置session过期时间
        return new SimpleAuthenticationInfo(userName, userPwd, getName());
    }
}

在customRealm中要重写doGetAuthenticationInfo方法作为登陆验证SecurityUtils.getSubject().getSession().setTimeout(1000 * 60);这句可以设置session的超时时间,单位是毫秒。

//将用户数据存储在session中 Session session = SecurityUtils.getSubject().getSession(); session.setAttribute("userSession", one);

上面两句则创建一个session并且将用户实体类one存储到seeeion中。

可以将存储的用户实体写作一个公共的controller,并且每一个controller去继承。

package com.example.springboot.controller;

import com.example.springboot.entity.UserEntity;
import org.apache.shiro.SecurityUtils;

public class BaseController {
    public UserEntity getUserSession() {
        UserEntity userSession = (UserEntity) SecurityUtils.getSubject().getSession().getAttribute("userSession");
        return userSession;
    }
}

接下来贴出登陆接口。

    @ApiOperation(value = "登陆")
    @PostMapping(value = "/login")
    public Result login(@RequestBody UserEntity user) {
        if (StringUtils.isNotBlank(user.getUserName()) && StringUtils.isNotBlank(user.getPassword())) {
            try {
                Subject subject = SecurityUtils.getSubject();
                UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUserName(), user.getPassword());
                subject.login(usernamePasswordToken);
            } catch (UnknownAccountException e) {
                return Result.error(CodeMsg.USERERROR, "账号不存在");
            } catch (LockedAccountException lock) {
                return Result.error(CodeMsg.USERERROR, "用户被锁定");
            } catch (IncorrectCredentialsException exception) {
                return Result.error(CodeMsg.USERERROR, "密码错误");
            }
            return Result.success("登陆成功");
        }
        return Result.error(CodeMsg.USERERROR, "用户名密码不能为空");
    }

subject.login会调用到customRealm中重写的doGetAuthenticationInfo方法。

以上内容都是个人瞎记录,有什么问题请大佬们指出。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值