关于Shiro框架的学习(一)

前言

由于最近在做一个项目,刚完成到登录注册,不想和以前的项目搬同样的砖了,想完成点不那么low的功能,像单点登录、权限控制等,于是就想起了Shiro框架。

初识Shiro

任何一种技术总有个开始,又总是这么巧,每个开始总是个HelloWorld。
官方给出的依赖:

shiro依赖

示例代码:

public class FirstShiro {

    private static final transient Logger log = LoggerFactory.getLogger(FirstShiro.class);
    public static void main(String[] args) {
        // TODO Auto-generated method stub

            log.info("My First Apache Shiro Application");
            System.exit(0);
    }
}

运行结果:

[main] INFO com.shiro.first.FirstShiro - My First Apache Shiro Application

Shiro概念

在没有Shiro的时候,我们在做项目中的登录、权限之类的功能有五花八门的实现方式,不同系统的做法不统一。但是有Shiro之后,大家就可以一致化地做权限系统,优点就是各自的代码不再晦涩难懂,有一套统一的标准。另外Shiro框架也比较成熟,能很好地满足需求。这就是我对Shiro的总结。

在Java SE中验证Shiro

Shiro不仅不依赖任何容器,可以在EE环境下运行,也可以在SE环境下运行,在快速入门中,我在SE环境下体验了Shiro的登录验证、角色验证、权限验证功能。

  • 配置文件方式

    • 在src目录下创建shiro.ini文件,内容如下:
      [users]
      #用户 密码 角色
    
      #博客管理员
      Object=123456,BlogManager
      #读者
      Reader=654321,SimpleReader
    
      #定义各种角色
      [roles]
      #博客管理员权限
      BlogManager=addBlog,deleteBlog,modifyBlog,readBlog
      #普通读者权限
      SimpleReader=readBlog,commentBlog
    
    • 创建用户实体类
    /**
     * @author Object
     *  用户实体类
     */
    public class User {
    
      private String name;
      private String password;
      public String getName() {
        return name;
      }
      public void setName(String name) {
        this.name = name;
      }
      public String getPassword() {
        return password;
      }
      public void setPassword(String password) {
        this.password = password;
      }
    
    }
    
    
    • 创建ShiroTest,验证登录、权限、角色:
      获取当前用户
    /**
     * 获取当前用户(Subject)
     * 
     * @param user
     * @return
     */
    public static Subject getSubject() {
        // 加载配置文件,获取SecurityManager工厂
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        // 从工厂中获取SecurityManager对象
        SecurityManager securityManager = factory.getInstance();
        // 通过SecurityUtil将SecurityManager对象放入全局对象
        SecurityUtils.setSecurityManager(securityManager);
        // 全局对象通过SecurityManager生成Subject
        Subject subject = SecurityUtils.getSubject();
        return subject;
    }
    
    登录:
    /**
     * 用户登录方法
     * 
     * @param user
     * @return
     */
    public static boolean login(User user) {
        Subject subject = getSubject();
        // 如果用户已经登录 则退出
        if (subject.isAuthenticated()) {
            subject.logout();
        }
        // 封装用户数据
        UsernamePasswordToken token = new UsernamePasswordToken(user.getName(), user.getPassword());
        // 验证用户数据
        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            // 登录失败
            // e.printStackTrace();为了看结果,暂时不让它打印
            return false;
        }
        return subject.isAuthenticated();
    }
    
    判断用户是否为某个角色:
    /**
     * 判断用户是否拥有某个角色
     * 
     * @param user
     * @param role
     * @return
     */
    public static boolean hasRole(User user, String role) {
        Subject subject = getSubject();
        return subject.hasRole(role);
    }
    
    
    判断用户是否拥有某项权限
    /**
     * 判断用户是否拥有某种权限
     * 
     * @param user
     * @param permit
     * @return
     */
    public static boolean isPermit(User user, String permit) {
        Subject subject = getSubject();
        return subject.isPermitted(permit);
    }
    
    有了这四个方法,我们就可以开始写测试类了。我会创建两个在配置文件中的用户 —— Object and Reader 和一个不在配置文件中的用户 —— Tom
        public static void main(String[] args) {
        // 用户Object
        User object = new User();
        object.setName("Object");
        object.setPassword("123456");
    
        // 用户Reader
        User reader = new User();
        reader.setName("Reader");
        // 错误的密码
        reader.setPassword("654321");
    
        // 不存在的用户
        User tom = new User();
        tom.setName("Tom");
        tom.setPassword("123456");
    
        List<User> users = new LinkedList<User>();
        users.add(object);
        users.add(reader);
        users.add(tom);
    
        // 角色:BlogManager
        String blogManager = "BlogManager";
        // 角色:SimpleReader
        String simpleReader = "SimpleReader";
    
        List<String> roles = new LinkedList<String>();
        roles.add(blogManager);
        roles.add(simpleReader);
    
        // 权限
        String addBlog = "addBlog";
        String deleteBlog = "deleteBlog";
        String modifyBlog = "modifyBlog";
        String readBlog = "readBlog";
        String commentBlog = "commentBlog";
        List<String> permits = new LinkedList<String>();
        permits.add(addBlog);
        permits.add(deleteBlog);
        permits.add(modifyBlog);
        permits.add(readBlog);
        permits.add(commentBlog);
        /**************************** 开始验证 ****************************/
        System.out.println("=========================验证用户是否登录成功=========================");
        // 验证用户是否登录成功
        for (User u : users) {
            if (login(u)) {
                System.out.println("用户:" + u.getName() + " 登录成功  " + "密码为:" + u.getPassword());
            } else {
                System.out.println("用户:" + u.getName() + " 登录失败  " + "密码为:" + u.getPassword());
            }
        }
        System.out.println("=========================验证用户角色信息=========================");
        // 验证用户角色
        for (User u : users) {
            for (String role : roles) {
                if (login(u)) {
                    if (hasRole(u, role)) {
                        System.out.println("用户:" + u.getName() + " 的角色是" + role);
                    }
                }
            }
        }
        System.out.println("=========================验证用户权限信息=========================");
        for(User u:users) {
            System.out.println("========================="+u.getName()+"权限=========================");
            for(String permit:permits) {
                if(login(u)) {
                    if(isPermit(u, permit)) {
                        System.out.println("用户:"+u.getName() +" 有 "+permit+" 的权限 ");
                    }
                }
            }
        }
    }
    

    运行结果如下(红字是由于缺少部分jar,暂不解决):


    SE运行结果

到这里为止,已经完成了Shiro的入门。但是在实际项目中,我们不可能用配置文件配置用户权限,所以还是得结合数据库进行开发。

Shiro结合数据库

  • RABC概念

要结合数据库进行开发,得先理解一个概念 —— RABC

RBAC 是当下权限系统的设计基础,同时有两种解释:
一: Role-Based Access Control,基于角色的访问控制
即:你要能够增删改查博客,那么当前用户就必须拥有博主这个角色。
二:Resource-Based Access Control,基于资源的访问控制
即,你要能够读博客、评论博客,那么当前用户就必须拥有读者这样的权限。

所以,基于这个概念,我们的数据库将有:用户表、角色表、权限表、用户——角色关系表、权限——角色关系表,其中用户角色关系为多对多,即一个用户可以对应多个角色,一个角色也可以由多个用户扮演,权限角色关系也为多对多,即一个角色可以有多个权限,一个权限也可以赋予多个角色。

  • 需要的Jar包

连接SQL.png
  • 数据库构建

    我使用的是MySQL,创建语句如下:

    CREATE DATABASE shiro;
    USE shiro;
    CREATE TABLE user(
      id bigint primary key auto_increment,
        name varchar(16),
        password varchar(32)
    )charset=utf8 ENGINE=InnoDB;
    
    create table role (
      id bigint primary key auto_increment,
      name varchar(32)
    ) charset=utf8 ENGINE=InnoDB;
    
    create table permission (
      id bigint primary key auto_increment,
      name varchar(32)
    ) charset=utf8 ENGINE=InnoDB;
    
    create table user_role (
      uid bigint,
      rid bigint,
      constraint pk_users_roles primary key(uid, rid)
    ) charset=utf8 ENGINE=InnoDB;
    
    create table role_permission (
      rid bigint,
      pid bigint,
      constraint pk_roles_permissions primary key(rid, pid)
    ) charset=utf8 ENGINE=InnoDB;
    

    往数据库中插入数据:

    INSERT INTO `user` VALUES (1,'Object','123456');
    INSERT INTO `user` VALUES (2,'Reader','654321');
    INSERT INTO `user_role` VALUES (1,1);
    INSERT INTO `user_role` VALUES (2,2);
    INSERT INTO `role` VALUES (1,'blogManager');
    INSERT INTO `role` VALUES (2,'reader');
    INSERT INTO `permission` VALUES (1,'addBlog');
    INSERT INTO `permission` VALUES (2,'deleteBlog');
    INSERT INTO `permission` VALUES (3,'modifyBlog');
    INSERT INTO `permission` VALUES (4,'readBlog');
    INSERT INTO `permission` VALUES (5,'commentBlog');
    INSERT INTO `role_permission` VALUES (1,1);
    INSERT INTO `role_permission` VALUES (1,2);
    INSERT INTO `role_permission` VALUES (1,3);
    INSERT INTO `role_permission` VALUES (1,4);
    INSERT INTO `role_permission` VALUES (2,4);
    INSERT INTO `role_permission` VALUES (2,5);
    
  • 工程构建

    • 创建实体类
    public class User {
        private int id;
        private String name;
        private String password;
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
    }
    
    • 修改shiro.ini配置文件
      因为我们要从数据库中获取用户、角色、权限信息,所以就不需要在配置文件中配置了,但是我们要有一个Realm的概念,Realm在我的理解中,可以把它当作一个桥梁,当用户(Subject)请求Realm时,Realm就会去寻找ini配置文件或者数据库中的用户信息,Realm就是真正对用户做验证的关卡。我们要在DatabaseRealm中重写两个方法,分别是验证用户授权,那么Shiro怎么找到Realm呢,就是靠shiro.ini配置文件。
    [main]
    databaseRealm=com.shirotest.DatabaseRealm
    securityManager.realms=$databaseRealm
    
    • 创建ShiroDao类
      这个类主要是从数据库中取出用户、权限列表、角色列表。
      代码如下:
    public class ShiroDao {
      private static Connection connection = null;
      private static PreparedStatement preparedStatement = null;
      static {
        try {
          Class.forName("com.mysql.jdbc.Driver");
          connection = DriverManager.getConnection(
              "jdbc:mysql://localhost:3306/shiro?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC",
              "root", "971103");
        } catch (ClassNotFoundException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    
      /**
       * 通过用户名获取密码
       * 
       * @param username
       * @return
       */
      public static String getPassword(String username) {
        String sql = "select password from user where name = ?";
        ResultSet rs = null;
        try {
          preparedStatement = connection.prepareStatement(sql);
          preparedStatement.setString(1, username);
          rs = preparedStatement.executeQuery();
          if (rs.next())
            return rs.getString("password");
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        return null;
      }
    
      public static Set<String> getRoles(String username) {
        String sql = "select role.name "
            + "from role,user_role,user "
            + "where user.id=user_role.uid "
            + "and user_role.rid=role.id "
            + "and user.name = ?";
        ResultSet rs = null;
        Set<String> set = new HashSet<>();
        try {
          preparedStatement = connection.prepareStatement(sql);
          preparedStatement.setString(1, username);
          rs = preparedStatement.executeQuery();
          while(rs.next()) {
            set.add(rs.getString("name"));
          }
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        return set;
      }
    
      public static Set<String> getPermits(String username) {
        String sql = "select permission.name "
            + "from"
            + " permission,role_permission,role ,user_role,user "
            + "where "
            + "permission.id = role_permission.pid "
            + "and role_permission.rid = role.id "
            + "and role.id = user_role.rid "
            + "and user_role.uid = user.id "
            + "and user.name = ?";
        ResultSet rs = null;
        Set<String> set = new HashSet<>();
        try {
          preparedStatement = connection.prepareStatement(sql);
          preparedStatement.setString(1, username);
          rs = preparedStatement.executeQuery();
          while (rs.next()) {
            set.add(rs.getString("name"));
          }
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        return set;
      }
    
      public static void main(String[] args) {
        System.out.println("Object的角色:" + new ShiroDao().getRoles("Object"));
        System.out.println("Reader的角色:" + new ShiroDao().getRoles("Reader"));
        System.out.println("Object的权限:"+new ShiroDao().getPermits("Object"));
        System.out.println("Reader的权限:"+new ShiroDao().getPermits("Reader"));
      }
    }
    

    运行结果:


    ShiroDao运行结果
    • DatabaseRealm
    public class DatabaseRealm extends AuthorizingRealm{
    
      /**
       *授权的方法
       */
      @Override
      protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        //只有认证成功了,Shiro才会调用这个方法进行授权
        //1.获取用户
        String username = (String) principal.getPrimaryPrincipal();
        //2.获取角色和权限列表
        Set<String> roles = ShiroDao.getRoles(username);
        Set<String> permissions = ShiroDao.getPermits(username);
        //3.授权
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(roles);
        simpleAuthorizationInfo.setStringPermissions(permissions);
    
        return simpleAuthorizationInfo;
      }
    
      /**
       *验证用户名密码是否正确的方法
       */
      @Override
      protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //1.获取用户名密码
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        //获取用户名
        String username = usernamePasswordToken.getUsername();
        //获取密码
        String password = usernamePasswordToken.getPassword().toString();
        //获取数据库中的密码
        String passwordInDatabase = ShiroDao.getPassword(username);
        //为空则表示没有当前用户,密码不匹配表示密码错误
        if(null == passwordInDatabase||!password.equals(passwordInDatabase)) {
          throw new AuthenticationException();
        }
        //认证信息:放用户名密码 getName()是父类的方法,返回当前类名
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,password,getName());
        return simpleAuthenticationInfo;
      }
    }
    
    • 测试类TestShiro
    public class TestShiro {
      public static void main(String[] args) {
        // 用户Object
          User object = new User();
          object.setName("Object");
          object.setPassword("123456");
    
          // 用户Reader
          User reader = new User();
          reader.setName("Reader");
          // 错误的密码
          reader.setPassword("654321");
    
          // 不存在的用户
          User tom = new User();
          tom.setName("Tom");
          tom.setPassword("123456");
    
          List<User> users = new LinkedList<User>();
          users.add(object);
          users.add(reader);
          users.add(tom);
    
          // 角色:BlogManager
          String blogManager = "blogManager";
          // 角色:SimpleReader
          String simpleReader = "reader";
    
          List<String> roles = new LinkedList<String>();
          roles.add(blogManager);
          roles.add(simpleReader);
    
          // 权限
          String addBlog = "addBlog";
          String deleteBlog = "deleteBlog";
          String modifyBlog = "modifyBlog";
          String readBlog = "readBlog";
          String commentBlog = "commentBlog";
          List<String> permits = new LinkedList<String>();
          permits.add(addBlog);
          permits.add(deleteBlog);
          permits.add(modifyBlog);
          permits.add(readBlog);
          permits.add(commentBlog);
          /**************************** 开始验证 ****************************/
          System.out.println("=========================验证用户是否登录成功=========================");
          // 验证用户是否登录成功
          for (User u : users) {
              if (login(u)) {
                  System.out.println("用户:" + u.getName() + " 登录成功  " + "密码为:" + u.getPassword());
              } else {
                  System.out.println("用户:" + u.getName() + " 登录失败  " + "密码为:" + u.getPassword());
              }
          }
          System.out.println("=========================验证用户角色信息=========================");
          // 验证用户角色
          for (User u : users) {
              for (String role : roles) {
                  if (login(u)) {
                      if (hasRole(u, role)) {
                          System.out.println("用户:" + u.getName() + " 的角色是" + role);
                      }
                  }
              }
          }
          System.out.println("=========================验证用户权限信息=========================");
          for(User u:users) {
              System.out.println("========================="+u.getName()+"权限=========================");
              for(String permit:permits) {
                  if(login(u)) {
                      if(isPermitted(u, permit)) {
                          System.out.println("用户:"+u.getName() +" 有 "+permit+" 的权限 ");
                      }
                  }
              }
          }
    
      }
      public static Subject getSubject() {
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //获取安全管理者实例
        SecurityManager sm = factory.getInstance();
        //将安全管理者放入全局对象
        SecurityUtils.setSecurityManager(sm);
        //全局对象通过安全管理者生成Subject对象
        Subject subject = SecurityUtils.getSubject();
        return subject;
      }
      public static boolean login(User user) {
        Subject subject = getSubject();
        if(subject.isAuthenticated()) {
          //如果登录了,就退出登录
          subject.logout();
        }
        //封装用户数据
        AuthenticationToken token = new UsernamePasswordToken(user.getName(),user.getPassword());
        try {
          subject.login(token);
        }catch(AuthenticationException e) {
          return false;
        }
        return subject.isAuthenticated();
      }
      private static boolean hasRole(User user, String role) {
        Subject subject = getSubject();
        return subject.hasRole(role);
      }
    
      private static boolean isPermitted(User user, String permit) {
        Subject subject = getSubject();
        return subject.isPermitted(permit);
      }
    }
    
    

    最终测试结果:


    最终测试结果

Shiro加密

我们在没有Shiro的时候,也会使用各种加密算法来对用户的密码进行加密,Shiro框架也提供了自己的一套加密服务,这里就说说MD5+盐。

在不加盐的MD5中,虽然密码也是使用非对称算法加密,同样也不能回转为明文,但是别人可以使用穷举法列出最常用的密码,例如12345 它加密后永远都是同一个密文,一些别有用心的人就可以通过这种常见密文得知你的密码是12345。但是加盐就不一样,他是在你的密码原文的基础上添加上一个随机数,这个随机数也会随之保存在数据库中,但是黑客拿到你的密码之后他并不知道哪个随机数是多少,所以就很难再破译密码。

操作一番。
首先要在数据库中加一个"盐"字段
ALTER TABLE user add column salt varchar(100)
同时在User实体类中加一个salt

  private String salt;
    public String getSalt() {
        return salt;
    }
    public void setSalt(String salt) {
        this.salt = salt;
    }

然后在ShiroDao中加一个注册用户的方法。

public static boolean registerUser(String username,String password) {
/***********************************Shiro加密***********************************/
        //获取盐值
        String salt = new SecureRandomNumberGenerator().nextBytes().toString();
        //加密次数
        int times = 3;
        //加密方式
        String type = "md5";
        //加密后的最终密码
        String lastPassword = new SimpleHash(type, password, salt, times).toString();
/***********************************加密结束***********************************/
    
        String sql = "INSERT INTO user(name,password,salt)VALUES(?,?,?)";
        try {
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, username);
            preparedStatement.setString(2, lastPassword);
            preparedStatement.setString(3, salt);
            if(preparedStatement.execute()) {
                return true;
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }
        return false;
    }

同时加一个获取用户的方法:

public static User getUser(String username) {
        String sql = "select * from user where name = ?";
        User user = new User();
        try {
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, username);
            ResultSet resultSet = preparedStatement.executeQuery();
            while(resultSet.next()) {
                user.setName(resultSet.getString("name"));
                user.setPassword(resultSet.getString("password"));
                user.setSalt(resultSet.getString("salt"));
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return user;
        
    }

修改之前的DatabaseRealm类中的验证用户方法,加一个将用户输入的密码加密后与数据库中密码进行比对的逻辑。具体逻辑如下:

//1.获取用户名密码
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
//获取用户名
String username = usernamePasswordToken.getUsername();
//获取密码
String password = new String(usernamePasswordToken.getPassword());
System.out.println("明文密码:"+password);
//获取数据库中的用户
User user = ShiroDao.getUser(usernamePasswordToken.getUsername());
//String passwordInDatabase = ShiroDao.getPassword(username);
        
        
//将用户输入的密码做一个加密后与数据库中的进行比对
String passwordMd5 = new SimpleHash("md5", password, user.getSalt(), 3).toString();
System.out.println("salt:"+user.getSalt());
System.out.println("密文密码:"+passwordMd5);
System.out.println("正在验证中......");
//为空则表示没有当前用户,密码不匹配表示密码错误
if(null == user.getPassword()||!passwordMd5.equals(user.getPassword())) {
    throw new AuthenticationException();
}
//认证信息:放用户名密码 getName9()是父类的方法,返回当前类名
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,password,getName());
return simpleAuthenticationInfo;

main测试:

    ShiroDao.registerUser("Object2", "321321");
        User object2 = new User();
        object2.setName("Object2");
        object2.setPassword("321321");
        if (login(object2)) {
            System.out.println("登录成功");
        } else {
            System.out.println("登录失败");
        }

最后结果:

加密结果

数据库结果:

数据库结果

第二种验证用户的方式

刚才我们是在doGetAuthenticationInfo方法中自己写了验证逻辑,再来捋一遍:

1.获取用户输入的密码
2.获取数据库中该用户的盐
3.将用户输入的密码进行加盐加密
4.将加密后的密码和数据库中的密码进行比对

大概是要经历这么多步骤吧。其实Shiro提供了一个HashedCredentialsMatcher ,可以自动帮我们做这些工作。

步骤:
1.修改配置文件

[main]
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName=md5 #加密方式
credentialsMatcher.hashIterations=3 #刚才我们指定的加密次数
credentialsMatcher.storedCredentialsHexEncoded=true

databaseRealm=com.shirotest.DatabaseRealm
securityManager.realms=$databaseRealm

2.修改doGetAuthenticationInfo方法

//1.获取用户名密码
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        //获取用户名
        String username = usernamePasswordToken.getUsername();
        //获取密码
        String password = new String(usernamePasswordToken.getPassword());
        System.out.println("明文密码:"+password);
        //获取数据库中的用户
        User user = ShiroDao.getUser(usernamePasswordToken.getUsername());
        //String passwordInDatabase = ShiroDao.getPassword(username);
        
        
        //将用户输入的密码做一个加密后与数据库中的进行比对
        System.out.println("数据库中密码:"+user.getPassword());
        String passwordMd5 = new SimpleHash("md5", password, user.getSalt(), 3).toString();
        System.out.println("salt:"+user.getSalt());
        System.out.println("密文密码:"+passwordMd5);
        System.out.println("正在验证中......");
        /*
         * //为空则表示没有当前用户,密码不匹配表示密码错误 if(null ==
         * user.getPassword()||!passwordMd5.equals(user.getPassword())) { throw new
         * AuthenticationException(); }
         */
        //认证信息:放用户名密码 getName9()是父类的方法,返回当前类名
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,user.getPassword(),ByteSource.Util.bytes(user.getSalt()),getName());
        return simpleAuthenticationInfo;

主要是修改了验证信息,将数据库中的密码和盐传入,让它自行判断,我们就无需再写判断逻辑了。SimpleAuthenticationInfo(username,user.getPassword(),ByteSource.Util.bytes(user.getSalt()),getName());

运行结果:


第二种方式运行结果

小结

到这里为止,Shiro关于SE的部分应该就告一段落了,之后要开始学习关于集成Web和集成框架了,我觉得对于Shiro的架构及原理,得单独浏览一遍,因为到此为止我也只知道Shiro是怎么使用的,但是其中Realm类中的那两个方法,何时调用,为什么会调用,还有SimpleAuthenticationInfo返回后是怎么判断登录成功或者失败的,可以说是很模糊,学完集成框架后我应该会选择再看看其中的原理。

欢迎大家访问我的个人博客:Object's Blog

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,039评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,426评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,417评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,868评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,892评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,692评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,416评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,326评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,782评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,957评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,102评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,790评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,442评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,996评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,113评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,332评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,044评论 2 355