apache shiro 如何升级_Shiro登录认证

    我们使用一个springboot+Shiro集成项目来了解一下Shiro在登录认证方面是如何运作的。

1、pom依赖添加

<dependency>            <groupId>org.apache.shirogroupId>            <artifactId>shiro-coreartifactId>            <version>1.2.2version>        dependency>        <dependency>            <groupId>org.apache.shirogroupId>            <artifactId>shiro-springartifactId>            <version>1.2.2version>        dependency>        <dependency>            <groupId>org.apache.shirogroupId>            <artifactId>shiro-ehcacheartifactId>            <version>1.2.2version>        dependency>

2.数据库用户权限表、实体类、用户权限DAO操作,略略略。

3.拦截器会在下一篇专门说明拦截器配置使用,略。

4.realm配置

        在Shiro中,最终是通过Realm来获取应用程序中的用户、角色及权限信息的。

public class MyShiroRealm extends AuthorizingRealm

通过继承公共Realm抽象类,实现认证处理逻辑抽象方法

c4fa7456986c0144923b72bb99d14085.png

@Override  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {    System.out.println("doGetAuthenticationInfo:" + token);    // 将AuthenticationToken强转为AuthenticationToken对象    UsernamePasswordToken upToken = (UsernamePasswordToken) token;    // 获得从表单传过来的用户名    String username = upToken.getUsername();    // 从数据库查看是否存在用户    UserService userService = new UserService();    // 如果用户不存在,抛此异常    if (!userService.selectUsername(username)) {      throw new UnknownAccountException("无此用户名!");    }    // 认证的实体信息,可以是username,也可以是用户的实体类对象,这里用的用户名    Object principal = username;    // 从数据库中查询的密码    Object credentials = userService.selectPassword(username);    // 颜值加密的颜,可以用用户名    ByteSource credentialsSalt = ByteSource.Util.bytes(username);    // 当前realm对象的名称,调用分类的getName()    String realmName = this.getName();    // 创建SimpleAuthenticationInfo对象,并且把username和password等信息封装到里面    // 用户密码的比对是Shiro帮我们完成的    SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);    return info;  }

然后在Config配置类中将自定义的realm加载到容器中:

@Configurationpublic class ShiroConfigBean {  @Bean    public MyShiroRealm myShiroRealm() {      MyShiroRealm myShiroRealm = new MyShiroRealm();      myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());      return myShiroRealm;    }}

容器启动时候会把这个Bean扫描进去,后边进行登录验证进行密码验证就会调用这个Bean,怎么调用的呢?往下看。

5.登录代码

@RequestMapping("/login.action")  public String login(String username, String password, Map map, HttpSession session) {    System.out.println(username + "---" + password);    // 获得当前Subject    Subject currentUser = SecurityUtils.getSubject();    // 验证用户是否验证,即是否登录    if (!currentUser.isAuthenticated()) {      String msg = "";      // 把用户名和密码封装为 UsernamePasswordToken 对象      UsernamePasswordToken token = new UsernamePasswordToken(username, password);      // remembermMe记住密码      token.setRememberMe(true);      try {        // 执行登录.        currentUser.login(token);        // 登录成功...        return "redirect:/LoginSuccess.action";      } catch (IncorrectCredentialsException e) {        msg = "登录密码错误";        System.out.println("登录密码错误!!!" + e);      } catch (ExcessiveAttemptsException e) {        msg = "登录失败次数过多";        System.out.println("登录失败次数过多!!!" + e);      } catch (LockedAccountException e) {        msg = "帐号已被锁定";        System.out.println("帐号已被锁定!!!" + e);      } catch (DisabledAccountException e) {        msg = "帐号已被禁用";        System.out.println("帐号已被禁用!!!" + e);      } catch (ExpiredCredentialsException e) {        msg = "帐号已过期";        System.out.println("帐号已过期!!!" + e);      } catch (UnknownAccountException e) {        msg = "帐号不存在";        System.out.println("帐号不存在!!!" + e);      } catch (UnauthorizedException e) {        msg = "您没有得到相应的授权!";        System.out.println("您没有得到相应的授权!" + e);      } catch (Exception e) {        System.out.println("出错!!!" + e);      }      map.put("msg", msg);      return "/index";    }    // 登录成功,重定向到LoginSuccess.action    return "redirect:/LoginSuccess.action";  }

上边一大堆代码,咱们只看三句就可以:

// 获得当前Subject(shiro核心类库中的方法)Subject currentUser = SecurityUtils.getSubject(); // 把用户名和密码封装为 UsernamePasswordToken 对象UsernamePasswordToken token = new UsernamePasswordToken(username, password);// 执行登录.currentUser.login(token);

上面三个方法都是Shiro类库中的方法,直接调用。

    用户从登录页将表单中用户名和密码传递过来后,封装成UsernamePasswordToken 对象传入到Shiro的登录入口方法login中,看一下login方法:

6d25e0be973865bd1833100cfc2c7803.png

进入securityManager安全管理器里边的login方法:

a4c5bb817b674bed17df6282bd4bbefa.png

然后一直往下走,找到获取Realms的方法:

076c27dcc0b0e738063210e7146c50e4.png

进入doSingleRealmAuthentication方法:

1ea1491574c3a8bc683b0cae0161c515.png

c38f40e8a26c3c8056c950ea1c9c0734.png

从shiro缓存中读取用户信息,如果没有,才从realm中获取信息。

点击这个doGetAuthenticationInfo方法,就到了我们第4步中进行realm配置时实现的抽象方法:

ad9b49727d32ebddd53e23c7dbf4c704.png

再进入这个实现方法时会出现我们配置的realm:

7a6b02d461fb9dbf753678f246f69084.png

以上步骤是通过我们自定义的realm根据表单信息查询数据库获取到数据库用户信息和表单信息的一个SimpleAuthenticationInfo 对象:

@param principal         the 'primary' principal associated with the specified realm.@param hashedCredentials the hashed credentials that verify the given principal.@param credentialsSalt   the salt used when hashing the given hashedCredentials@param realmName         the realm from where the principal and credentials were acquired.SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(  principal, //认证的实体信息,可以是实体类也可以是用户名  hashedCredentials , //用于跟表单密码进行比对的已存储的密码值  credentialsSalt, //已存储密码加密算法中使用的盐值  realmName //realm的名称);

然后才开始进行密码验证。

6、密码验证

ca3baf7b6adc70c7064b181f629e2510.png

获取到SimpleAuthenticationInfo 对象,开始使用算法进行比较。

assertCredentialsMatch(token, info);

token中保存了表单信息,info中保存了数据库中密码信息。

9a60583ca49b7bd2bdd3203e4a4f732a.png

        首先需要获取指定的凭证匹配器,就是使用哪种算法(常见的散列算法如MD5、SHA等,加密算法会在加密章进行讲解)来进行验证,把表单中的密码通过加盐算法进行计算,得出的值与数据库中的值进行比较,相同就验证通过。

可以在realm配置时进行指定:

@Bean  public HashedCredentialsMatcher hashedCredentialsMatcher() {    HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();    hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;    hashedCredentialsMatcher.setHashIterations(1024);// 散列的次数,比如散列两次,相当于md5(md5(""));    return hashedCredentialsMatcher;  }  @Bean  public MyShiroRealm myShiroRealm() {    MyShiroRealm myShiroRealm = new MyShiroRealm();    myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());    return myShiroRealm;  }

看完之后,明白了吗?没有的话再看一遍!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值