当前位置: 移动技术网 > IT编程>开发语言>Java > SpringSecurity动态加载用户角色权限实现登录及鉴权

SpringSecurity动态加载用户角色权限实现登录及鉴权

2019年11月27日  | 移动技术网IT编程  | 我要评论

file

很多人觉得spring security实现登录验证很难,我最开始学习的时候也这样觉得。因为我好久都没看懂我该怎么样将自己写的用于接收用户名密码的controller与spring security结合使用,这是一个先入为主的误区。后来我搞懂了:根本不用你自己去写controller。你只需要告诉spring security用户信息、角色信息、权限信息、登录页是什么?登陆成功页是什么?或者其他有关登录的一切信息。具体的登录验证逻辑它来帮你实现。

一、动态数据登录验证的基础知识

在本号之前的文章中,已经介绍了spring security的formlogin登录认证模式,rbac的权限控制管理模型,并且针对spring security的登录认证逻辑源码进行了解析等等。我们所有的用户、角色、权限信息都是在配置文件里面写死的,然而在实际的业务系统中,这些信息通常是存放在rbac权限模型的数据库表中的。下面我们来回顾一下其中的核心概念:

  • rbac的权限模型可以从用户获取为用户分配的一个或多个角色,从用户的角色又可以获取该角色的多种权限。通过关联查询可以获取某个用户的角色信息和权限信息。
  • 在源码解析的文章中,我们知道如果我们不希望用户、角色、权限信息写死在配置里面。我们应该实现userdetails与userdetailsservice接口,从而从数据库或者其他的存储上动态的加载这些信息。

以上是对一些核心的基础知识的总结,如果您对这些知识还不是很清晰,建议您先往下读本文。如果看完本文仍然理解困难,建议您翻看本号之前的文章。

二、userdetails与userdetailsservice接口

  • userdetailsservice接口有一个方法叫做loaduserbyusername,我们实现动态加载用户、角色、权限信息就是通过实现该方法。函数见名知义:通过用户名加载用户。该方法的返回值就是userdetails。
  • userdetails就是用户信息,即:用户名、密码、该用户所具有的权限。

下面我们来看一下userdetails接口都有哪些方法。

public interface userdetails extends serializable {
    //获取用户的权限集合
    collection<? extends grantedauthority> getauthorities();

    //获取密码
    string getpassword();

    //获取用户名
    string getusername();

    //账号是否没过期
    boolean isaccountnonexpired();

    //账号是否没被锁定
    boolean isaccountnonlocked();

    //密码是否没过期
    boolean iscredentialsnonexpired();

    //账户是否可用
    boolean isenabled();
}

现在,我们明白了,只要我们把这些信息提供给spring security,spring security就知道怎么做登录验证了,根本不需要我们自己写controller实现登录验证逻辑。

三、实现userdetails 接口

public class sysuser implements userdetails{
    
    string password();  //密码
    string username();  //用户名
    boolean accountnonexpired;   //是否没过期
    boolean accountnonlocked;   //是否没被锁定
    boolean credentialsnonexpired;  //是否没过期
    boolean enabled;  //账号是否可用
    collection<? extends grantedauthority> authorities;  //用户的权限集合

    //省略构造方法
    //省略set方法
    //省略get方法(即接口userdetails的方法)
}

我们就是写了一个适应于userdetails的java pojo类,所谓的 userdetails接口实现就是一些get方法。get方法由spring security调用,我们通过set方法或构造函数为 spring security提供userdetails数据。

四、实现userdetailsservice接口

@component
public class myuserdetailsservice implements userdetailsservice{

    @override
    public userdetails loaduserbyusername(string username) throws usernamenotfoundexception {
            
       //这里从数据库sys_user表里面查询实体类对象。loaduser方法可使用mybatis或jdbc或jpa自行实现。
       sysuser sysuser =  loaduser(username);   

        // 判断用户是否存在 
       if(user == null)  {  throw  new  usernamenotfoundexception("用户名不存在");  }

       //从数据库该用户所有的角色信息,所有的权限标志
       //遍历所有的role角色及所有的authority权限(菜单、按钮)。
       //用逗号分隔他们的唯一标志,具体过程自行实现。
       sysuser.setauthorities(
               authorityutils.commaseparatedstringtoauthoritylist("role_amin , system:user:delete"));
        
        //sysuser.setaccountnonlocked(true或false);
        return sysuser;
    }
}
  • 通常数据库表sys_user字段要和sysuser属性一一对应,比如username、password、enabled。但是比如accountnonlocked字段用于登录多次错误锁定,但我们一般不会在表里存是否锁定,而是存一个锁定时间字段。通过锁定时间是否大于当前时间判断账号是否锁定,所以实现过程中可以灵活做判断并用好set方法,不必拘泥于一一对应的形式。
  • 角色是一种特殊的权限,在spring security我们可以使用hasrole(角色标识)表达式判断用户是否具有某个角色,决定他是否可以做某个操作;通过hasauthority(权限标识)表达式判断是否具有某个操作权限。

五、最后说明

至此,我们将系统里面的所有的用户、角色、权限信息都通过userdetailsservice和userdetails告知了spring security。但是多数朋友可能仍然不知道该怎样实现登录的功能,其实剩下的事情很简单了:

  • 写一个登录界面,写一个登录表单,表单使用post方法提交到默认的/login路径
  • 表单的用户名、密码字段名称默认是username、password。
  • 写一个登录成功之后的跳转页面,比如

然后把这些信息通过配置方式告知spring security ,以上的配置信息名称都可以灵活修改。如果您不知道如何配置请参考本号之前的文章《formlogin登录认证模式》。

期待您的关注

  • 向您推荐博主的系列文档:
  • 本文转载注明出处(必须带连接,不能只转文字):。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网