Apache Shiro安全框架实现身份认证(登陆与登出)

写在前边:Shiro是非常强大的安全框架,与Spring security相比,它更容易上手。
公众号:小白编码

Shiro介绍:

Apache Shiro 是 Java 的一个安全(权限)框架

Subject:正如我们在刚才提到教程,在Subject本质上是当前正在执行的用户的安全特定“视图”。“用户”一词通常表示一个人,一个人Subject可以是一个人,但它也可以表示第三方服务,守护程序帐户,cron作业或类似的东西-基本上是当前与该软件交互的任何东西。

Subject实例都绑定到(并要求)SecurityManager。当您与互动时Subject,这些互动会转化为与主题相关的互动SecurityManager。

SecurityManager:SecurityManager是Shiro体系结构的核心,并充当一种“伞”对象,可协调其内部安全组件,这些组件一起形成对象图。但是,一旦为应用程序配置了SecurityManager及其内部对象图,通常就不理会它,并且应用程序开发人员几乎所有的时间都花在SubjectAPI上。

Realms:领域充当Shiro与应用程序的安全数据之间的“桥梁”或“连接器”。当真正需要与安全性相关的数据(例如用户帐户)进行交互以执行身份验证(登录)和授权(访问控制)时,Shiro会从一个或多个为应用程序配置的领域中查找许多此类内容。
组件流程:
在这里插入图片描述

Shiro的架构:
在这里插入图片描述

搭建环境

Springboot+mybatis+mysql+shiro

user表:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) NOT NULL,
  `password` varchar(50) NOT NULL,
  `nick_name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

user类:

@Data
public class User {
    private Integer id;
    private String username;
    private String password;
    private String nickName;
}

UserMapper:

public interface UserMapper {

    @Select("select * from user where username = #{username}")
    User findUserByUserName(String username);
}

UserService:

public interface UserService {
    /**
     * 根据用户名查询用户信息
     * @param username
     * @return
     */
    User findUserByUserName(String username);
}

@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public User findUserByUserName(String username) {
        return userMapper.findUserByUserName(username);
    }
}

Shiro配置UserRealm:

public class UserRealm extends AuthorizingRealm {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserRealm.class);

    @Autowired
    private UserService userService;

    /**
     * 授权逻辑
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行授权逻辑!");
        return null;
    }

    /**
     * 认证逻辑
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行认证逻辑!");
		//当前登陆的token信息
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //获取用户:使用token判断用户名
        User user = userService.findUserByUserName(token.getUsername());
        //如果用户不存在:
        if (user == null) {
            LOGGER.info("用户不存在{}");
            //返回null,底层抛出异常:UnKnowAccountException
            return null;

        }
		//2.判断密码 : user会传到Subject中
        return new SimpleAuthenticationInfo(user, user.getPassword(), "");
    }
}

ShiroConfig:

@Configuration
public class ShiroConfig {

    /**
     * 安全过滤器
     * @param defaultWebSecurityManager 安全管理器
     * @return 返回Shiro过滤器工厂
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        //设置登陆的url
        shiroFilterFactoryBean.setLoginUrl("/login");
        return shiroFilterFactoryBean;
    }

    /**
     * 默认安全管理器
     * @param userRealm 关联的自定义Realm
     * @return 默认安全管理器
     */
    @Bean("securityManager")
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {

        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        //关联realm
        manager.setRealm(userRealm);
        return manager;
    }

    /**
     * 创建Realm(Shiro连接数据的桥梁)
     * @return 返回一个Realm
     */
    @Bean("userRealm")
    public UserRealm gerUserRealm() {
        return new UserRealm();
    }
}

执行登陆功能:

    /**
     * 登陆逻辑
     * @param user
     * @return
     */
    @PostMapping("/login")
    @ResponseBody
    public Result login(User user) {
        
        if (user != null) {
             //1. 获取subject 用户主体
            Subject subject = SecurityUtils.getSubject();
            //2. 封装用户数据Token登陆
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
            try {
                //3.执行登陆方法
                subject.login(token);
                //没有异常抛出就是登陆成功!
                return Result.success("登陆成功!");
            } catch (UnknownAccountException e) {
                //UnknownAccountException异常:用户名不存在  
                return Result.failure("用户不存在!");
            } catch (IncorrectCredentialsException e) {
                //IncorrectCredentialsException异常:密码错误  
                return Result.failure("密码错误!");
            }

        }
        //如果参数为空
        return Result.failure("登陆参数不能为空!");
    }

结果:

{
    "code": 200,
    "message": "处理成功!",
    "data": "登陆成功!"
}

执行登出功能:

/**
 * 退出登陆
 * @return
 */
@GetMapping("/logout")
@ResponseBody
public Result logout() {
    //获取当前主体
    Subject subject = SecurityUtils.getSubject();

    //如果已登录
    if (subject.isAuthenticated()) {
        //退出登陆
        subject.logout();
        return Result.success("退出成功!");

    }
    return Result.failure("退出失败!");

}

执行结果:

{
    "code": 200,
    "message": "处理成功!",
    "data": "退出成功!"
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值