前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Shiro系列 | 《Shiro开发详细教程》第二章:Shiro身份认证

Shiro系列 | 《Shiro开发详细教程》第二章:Shiro身份认证

作者头像
码神联盟
发布2018-11-05 18:29:01
1.4K0
发布2018-11-05 18:29:01
举报
文章被收录于专栏:码神联盟码神联盟

本文目录:

► 第二章:Shiro身份认证

► 2.1 身份认证

► 2.2 环境准备

► 2.3 登录、退出

下节文章预告

► 第二章:Shiro身份认证(预告)

► 2.4 身份认证流程(预告)

2.1 身份认证

身份验证,即在应用中谁能证明他就是他本人。一般提供如他们的身份 ID 一些标识信息来表明他就是他本人,如提供身份证,用户名 / 密码来证明。

在Shiro中,用户需要提供principals (身份)和credentials(证明)给 shiro,从而应用能验证用户身份:

principals:身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。一个主体可以有多个 principals,但只有一个 Primary principals,一般是用户名 / 密码 / 手机号。

credentials:证明 / 凭证,即只有主体知道的安全值,如密码 / 数字证书等。

另外两个相关的概念是之前提到的 SubjectRealm,分别是主体及验证主体的数据源。

最常见的 principals 和 credentials 组合就是用户名 / 密码了。

接下来先进行一个基本的身份认证。

2.2 环境准备

环境要求:Maven、IDEA

  • 新建Maven工程,并且导入以下Jar包依赖 (添加 junit、common-logging 及 shiro-core 依赖、log4j、slfj-api等即可):
代码语言:javascript
复制
<dependencies>
    <!--Shiro核心包-->
  <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.4.0</version>
  </dependency>
    <!--junit测试包-->
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
  </dependency>
  <!--日志管理包-->
  <dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
  </dependency>
  <dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.12</version>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.25</version>
  </dependency>
</dependencies>

2.3 登录、退出

  • 准备初始值数据到属性文件中(shiro.ini)
代码语言:javascript
复制
[users]
zhangsan=mima
sunwukong=mima

说明:使用 ini 配置文件,通过 [users] 指定了两个主体:zhang/ mima、sunwukong / mima.

  • 添加log4j的日志输出格式定义文件log4j.properties
代码语言:javascript
复制
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
# General Apache libraries
log4j.logger.org.apache=WARN
# Spring
log4j.logger.org.springframework=WARN
# Default Shiro logging
log4j.logger.org.apache.shiro=TRACE
# Disable verbose logging
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN
  • 增加测试类,测试主体信息(com.ms.ShiroTest)
  • 获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
  • 得到SecurityManager实例 并绑定给SecurityUtils
  • 得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
  • 登录,即身份验证
  • 身份验证成功与否具体信息
  • 退出

具体代码如下:

代码语言:javascript
复制
/**
 * @Auther: likang
 * @Description: shiro登录、退出功能演示
 */
public class ShiroTest {

    public static final Logger logger = LoggerFactory.getLogger(ShiroTest.class);

    public static void main(String[] args) {
        //1:获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //2:得到SecurityManager实例 并绑定给SecurityUtils
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        //3:得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
        Subject subject = SecurityUtils.getSubject();
        //4:登录,即身份验证
        if (!subject.isAuthenticated()){
            UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "mima2");
           try {
                subject.login(token);
                logger.info("登录成功");
            } catch (UnknownAccountException e) {
            //5:身份验证失败
                logger.info("用户名错误或者不存在");
            } catch (IncorrectCredentialsException e){
                logger.info("密码不匹配");
            } catch (LockedAccountException e){
                logger.info("用户已被锁定,请联系管理员");
            } catch (DisabledAccountException e){
                logger.info("用户已被禁用,请联系管理员");
            } catch (ExcessiveAttemptsException e){
                logger.info("用户登录次数过多");
            } catch (AuthenticationException  e){
                logger.info("用户登录失败,请联系管理员");
            }
        }
        subject.logout();//6:退出
    }
}

代码梳理:

  • 首先通过 new IniSecurityManagerFactory 并指定一个 ini 配置文件来创建一个 SecurityManager 工厂;
  • 接着获取 SecurityManager 并绑定到 SecurityUtils,这是一个全局设置,设置一次即可;
  • 通过 SecurityUtils 得到 Subject,其会自动绑定到当前线程;如果在 web 环境在请求结束时需要解除绑定;然后获取身份验证的 Token,如用户名 / 密码;
  • 调用 subject.login 方法进行登录,其会自动委托给 SecurityManager.login 方法进行登录;
  • 如果身份验证失败请捕获 AuthenticationException 或其子类,常见的如:

DisabledAccountException(禁用的帐号)、

LockedAccountException(锁定的帐号)、

UnknownAccountException(错误的帐号)、

ExcessiveAttemptsException(登录失败次数过多)、

IncorrectCredentialsException (错误的凭证)、

ExpiredCredentialsException(过期的凭证)等,

对于页面的错误消息展示,最好使用如 “用户名 / 密码错误” 而不是 “用户名错误”/“密码错误”,防止一些恶意用户非法扫描帐号库;

  • 最后可以调用 subject.logout 退出,其会自动委托给 SecurityManager.logout 方法退出。

从如上代码可总结出身份验证的步骤

  • 收集用户身份 / 凭证,即如用户名 / 密码;
  • 调用 Subject.login 进行登录,如果失败将得到相应的 AuthenticationException 异常,根据异常提示用户错误信息;否则登录成功;
  • 最后调用 Subject.logout 进行退出操作。

需要解决的问题?

  • 用户名 / 密码硬编码在 ini 配置文件,以后需要改成如数据库存储,且密码需要加密存储;
  • 用户身份 Token 可能不仅仅是用户名 / 密码,也可能还有其他的,如登录时允许用户名 / 邮箱 / 手机号同时登录。

可以留言欢迎讨论,如何解决这些问题,答案下期揭晓。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码神联盟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
多因子身份认证
多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档