iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >springboot中怎么利用shiro实现多验证登录功能
  • 907
分享到

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

2023-06-20 15:06:09 907人浏览 独家记忆
摘要

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

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);    }

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

--结束END--

本文标题: springboot中怎么利用shiro实现多验证登录功能

本文链接: https://www.lsjlt.com/news/297810.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作