文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

springboot中怎么利用shiro实现多验证登录功能

2023-06-20 15:19

关注

springboot中怎么利用shiro实现多验证登录功能,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

首先新建一个shiroConfig shiro的配置类,代码如下:

@Configurationpublic class SpringShiroConfig {        @Bean    public SecurityManager securityManager(Collection<Realm> realms) {        DefaultWebSecurityManager sManager = new DefaultWebSecurityManager();        sManager.setRealms(realms);        return sManager;    }    @Bean    public ShiroFilterFactoryBean shiroFilterFactory(SecurityManager securityManager) {        ShiroFilterFactoryBean sfBean = new ShiroFilterFactoryBean();        sfBean.setSecurityManager(securityManager);        //如果是匿名访问时,访问了不能访问的资源跳转的位置        sfBean.setLoginUrl("/index");        //定义map指定请求过滤规则(哪些资源允许匿名访问,哪些必须认证访问)        LinkedHashMap<String, String> map = new LinkedHashMap<>();        //静态资源允许匿名访问:"anon" 静态资源授权时不能写static下面所有的开放,要将static下面的所有文件夹一个一个的开放,templates同理        //map的key可以为文件的位置,也可以为请求的路径        map.put("/bower_components    @Override    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {                HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();        //这里是设置加密方式        matcher.setHashAlgorithmName("MD5");        //这里是设置加密的次数        matcher.setHashIterations(2);        super.setCredentialsMatcher(matcher);    }        @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        return null;    }        @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {        //先判断这个是否是来及这个令牌的数据:我们这儿分为了UsernamePasswordToken(shiro给我们提供的。)、UserPhoneToken        if (!(authenticationToken instanceof UsernamePasswordToken)) {            return null;        }        //获取controller传过来的数据        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;        //upToken.setRememberMe(true);shiro默认为false,是是否记住我的功能        //这儿为用户提交的username        String username = upToken.getUsername();        //去数据更加name取到用户的信息        User user = userDao.findUserByUserName(username);        //判断数据库是否有这用户        if (user == null) {            throw new UnknownAccountException();        }        //判断用户的状态是否被禁用(数据库的字段)        if (user.getState() == 0) {            throw new LockedAccountException();        }        //这儿是取到用户信息中的盐值,盐值要转换为ByteSource这个类型才能使用        ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());        //这儿是将这个用户的信息交给shiro(user为用户对象,user.getPassword()是要加密的对象,credentialsSalt为盐值,getName()当前对象)        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), credentialsSalt, getName());        return info;    }}

此时用户的账号密码登录已经可以使用了controller代码如下:

@RequestMapping("userPasswordLogin")    @ResponseBody    public JsonResult userPasswordLogin(String username, String password) {        Subject subject = SecurityUtils.getSubject();        UsernamePasswordToken token = new UsernamePasswordToken(username, password);        subject.login(token);        return new JsonResult("login Ok");    }

我们现在来实现短信验证码登录实现:

1 先写UserPhoneToken,我放在l和springShiroConfig同一目录下:

@Componentpublic class UserPhoneToken extends UsernamePasswordToken implements Serializable {    private static final long serialVersionUID = 6293390033867929958L;    // 手机号码    private String phoneNum;    //无参构造    public UserPhoneToken(){}        //获取存入的值    @Override    public Object getPrincipal() {        if (phoneNum == null) {            return getUsername();        } else {            return getPhoneNum();        }    }    @Override    public Object getCredentials() {        if (phoneNum == null) {            return getPassword();        }else {            return "ok";        }    }    public UserPhoneToken(String phoneNum) {        this.phoneNum = phoneNum;    }    public UserPhoneToken(final String userName, final String password) {        super(userName, password);    }    public String getPhoneNum() {        return phoneNum;    }    public void setPhoneNum(String phoneNum) {        this.phoneNum = phoneNum;    }    @Override    public String toString() {        return "PhoneToken [PhoneNum=" + phoneNum + "]";    }}

2 在写shiroUserPhoneRealm,代码如下:

@Servicepublic class ShioUserPhoneRealm extends AuthorizingRealm {    @Autowired    private UserDao userDao;    @Override    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {        //这儿的CredentialsMatcher的new的对象必须是AllowAllCredentialsMatcher        CredentialsMatcher matcher = new AllowAllCredentialsMatcher();        super.setCredentialsMatcher(matcher);    }    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        return null;    }        @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {        UserPhoneToken token = null;        if (authenticationToken instanceof UserPhoneToken) {            token = (UserPhoneToken) authenticationToken;        }else {            return null;        }        //获取我发送验证码是存入session中的验证码和手机号        String verificationCode = (String) SecurityUtils.getSubject().getSession().getAttribute("verificationCode");        String phone = (String) SecurityUtils.getSubject().getSession().getAttribute("phone");        //获取controller传过来的数据        String verificationCode1 = (String) token.getPrincipal();        //去数据库根据手机号查询用户信息        User user = userDao.findUserByUserPhone(phone);        if (StringUtils.isEmpty(verificationCode)) {            throw new ServiceException("网络错误");        }        //比对手机号        if (!verificationCode.equals(verificationCode1)) {            throw new ServiceException("验证码不正确");        }        if (user == null) {            throw new UnknownAccountException();        }        if (user.getState() == 0) {            throw new LockedAccountException();        }        return new SimpleAuthenticationInfo(user,phone,getName());    }}

3 手机号码登录验证已经基本完成:controller代码如下:

@PostMapping("verificationCodeLogin")    @ResponseBody    public JsonResult verificationCodeLogin(String password) {        Subject subject = SecurityUtils.getSubject();        UserPhoneToken token = new UserPhoneToken(password);        subject.login(token);        return new JsonResult("login OK");    }

使用过程中遇到的bug

org.apache.shiro.authc.UnknownAccountException: Realm [cn.tedu.wxacs.service.impl.ShioUserPhoneRealm@768d8431] was unable to find account data for the submitted AuthenticationToken [org.apache.shiro.authc.UsernamePasswordToken - 张三, rememberMe=false].

出现这个问题是我的是因为Realm中的某个实现类没有加注解,我这儿演示时是应为ShiroUserRealm为加@Service注解

org.apache.shiro.authc.AuthenticationException: Authentication token of type [class org.apache.shiro.authc.UsernamePasswordToken] could not be authenticated by any configured realms.  Please ensure that at least one realm can authenticate these tokens.

这儿出现的问题是应为我的ShioUserRealm的AuthenticationInfo方法的User user = userDao.findUserByUserName(username);这行代码出现的问题,debug的时候就发现这一句执行后就保错

原因:是因为我的application.yml文件中没有写dao对应的mapper文件的路径

在ShioUserPhoneRealm的doGetAuthenticationInfo方法的new SimpleAuthenticationInfo(user,phone,getName())这个位置后就报错是应为ShioUserPhoneRealm的这个方法中你没有将new的对象设置为AllowAllCredentialsMatcher();

@Override    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {        //这儿的CredentialsMatcher的new的对象必须是AllowAllCredentialsMatcher        CredentialsMatcher matcher = new AllowAllCredentialsMatcher();        super.setCredentialsMatcher(matcher);    }

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网行业资讯频道,感谢您对编程网的支持。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯