Shiro登录验证

1.首先需要导入Shiro依赖包

<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-spring</artifactId>
	<version>1.3.2</version>
</dependency>

2.定义自己的Reaml 需要继承AuthenticatingRealm 重写doGetAuthenticationInfo()方法;
AuthenticatingRealm 是用于完成用户身份验证的抽象类

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        //获取用户身份令牌
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        //获取用户在页面中输入的账号
        String username = token.getUsername();
        /*
        * 验证账号是否正确
        * 实际工作中应该从数据库中获取数据
        * 注意:
        *   如果验证失败需要手动抛出异常AuthenticationException以及其子类异常
        *   AuthenticationException常用子类
        *   AccountException 用户账号异常
        *   UnknownAccountException 账号错误异常
        *   LockedAccountException 账户被冻结异常
        *   IncorrectCredentialsException 密码错误异常
        */
        if (!"admin".equals(username)&&!"zhangsan".equals(username)){

            throw new UnknownAccountException("账号输入错误");
        }else if ("zhangsan".equals(username)){
            throw new LockedAccountException("账号被冻结");
        }
        //数据库中的密码,
        String dbPassword = "123456";
        //返回验证密码的对象,Shiro会自定根据对象的数据用来验证密码是否正确
        //如果验证是白Shiro会抛出一个异常信息IncorrectCredentialsException
        return new SimpleAuthenticationInfo(username,dbPassword,this.getName());

3.写Shiro的配置类,将自定义的MyReaml,Shiro的安全管理器:SecurityManager,Shiro过滤器:ShiroFilterFactoryBean注册到Spring的上下文中

@Configuration
public class ShiroConfig {

    //将自定义的realm类注入到容器中
    @Bean
    public Realm myRealm(){
        return new MyRealm();
    }

    @Bean
    public SecurityManager securityManager(Realm myRealm){
        return new DefaultWebSecurityManager(myRealm);
    }

    //将shiro的过滤器定义到spring的应用上下文中去
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        //设置完全管理器
        factoryBean.setSecurityManager(securityManager);
        factoryBean.setLoginUrl("/");//设置如果用户没有登录后转向的页面
        factoryBean.setSuccessUrl("/success");//设置登录成功后跳转的页面
        factoryBean.setUnauthorizedUrl("/noperms");//设置没有权限后的转向地址
        LinkedHashMap<String,String> chain = new LinkedHashMap();
        //配置/logout 为登出请求,用户Shiro清空会话中的数据并自动返回未登录所转向的页面
        chain.put("/logout", "logout");
        //配置/login用户登录请求不需要登录即可访问
        chain.put("/login", "anon");
        //设置以admin开头的所有请求必须登录后才可以访问
        chain.put("admin/**", "authc");
        chain.put("user/**", "authc");
        //设置所以请求必须要登录后才能访问,由于范围比较大因此一定要写在最后的位置
        //注意:由于是拦截了所以请求都需要登录,这些请求也包括静态资源,例如js,css,图片
        chain.put("/**", "authc");
        factoryBean.setFilterChainDefinitionMap(chain);//
        return factoryBean;
    }   
}

4.在Controller层中定义登录方法login

    @RequestMapping("/login")
    public String login(String username, String password, Model model){
        //获取当前操作对象
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        /*
        * 判断当前的操作用户是否完成了用户登录认证,(用户是否登录)进入if表示用户已经登录
        * 如果写了这个if那么用户将无法重复登录,因为在Subject中只要用户登录成功就会将用户
        * 信息记录到Subject中,因此isAuthenticated 这个方法返回true
        * 如果需要用户能够再次登录有3中解决方案
        *   1.不写这个if,但是会造成重复发送用户登录请求,增加服务器压力
        *   2.调用Subject中的logout()方法,用于退出当前的登录状态,清空会话中的所用数据
        *   3.在页面中编写一个安全退出请求,用于用户主动退出登录状态
        *
        */
        if (subject.isAuthenticated()){
            return "redirect:/success";
        }
        //到了这里表示用户没有登录
        //调用用户登录方法,后台Shiro会自动执行MyRealm中的用户认证方法doGetAuthenticationInfo
        //如果登录成功login方法将正常结束否则将抛出异常,我们要更具异常信息对用户进行友好提示
        try {

            subject.login(token);
        }catch (UnknownAccountException e){
            model.addAttribute("errMsg", "登录失败,账号不存在");
            return "index";

        }catch (LockedAccountException e){
            model.addAttribute("errMsg", "登录失败,账号以冻结");
            return "index";

        }catch (IncorrectCredentialsException e){
            model.addAttribute("errMsg", "登录失败,密码错误");
            return "index";
        }catch (AuthenticationException e){
            model.addAttribute("errMsg", "登录失败");
            return "index";
        }
        //登录成功,不需要记录Session会话,Shiro会将这些用户状态信息记录到会话中(记录在Subject中)
        return "redirect:/success";

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值