shiro学习二

shiro学习二

认证:

1. 认证流程:

  1. 获取当前的 Subject. 调用 SecurityUtils.getSubject();

  2. 测试当前的用户是否已经被认证. 即是否已经登录. 调用 Subject 的 isAuthenticated()

  3. 若没有被认证, 则把用户名和密码封装为 UsernamePasswordToken 对象

  4. 执行登录: 调用 Subject 的 login(AuthenticationToken) 方法.

  5. 自定义 Realm 的方法, 从数据库中获取对应的记录, 返回给 Shiro.
    1). 实际上需要继承 org.apache.shiro.realm.AuthenticatingRealm 类
    2). 实现 doGetAuthenticationInfo(AuthenticationToken) 方法.

  6. 由 shiro 完成对密码的比对.

在这里插入图片描述

2.代码

login.jsp页面代码 ,用于接收用户名和密码

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<form action="shiro/login" method="POST">
    username: <input type="text" name="username"/>
    <br><br>

    password: <input type="password" name="password"/>
    <br><br>

    <input type="submit" value="Submit"/>
</form>
</body>
</html>

controller 代码

@Controller
@RequestMapping("/shiro")
public class shiroLogin {

    @RequestMapping("/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password){
        //获得当前用户的subject
        Subject currentUser = SecurityUtils.getSubject();
         //判断当前用户是否被授权
        if (!currentUser.isAuthenticated()) {
            // 把用户名和密码封装为 UsernamePasswordToken 对象
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
 
            try {
                // 执行登录. 将token 传到 doGetAuthenticationInfo
                currentUser.login(token);
            }
            // ... catch more exceptions here (maybe custom ones specific to your application?
            // 所有认证时异常的父类.
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
                System.out.println("登录失败: " + ae.getMessage());
            }
        }
        //邓露成功后重定向到list.jsp
        return "redirect:/list.jsp";
    }
}

自定义Realm代码

上次我们自定义的realm类仅仅实现了Realm接口,如果我们要做认证,那么我们需要继承AuthenticatingRealm类,并重写doGetAuthenticationInfo方法。执行subject.login(token)方法后,就会来到 doGetAuthenticationInfo()里。

public class CustomRealm extends AuthenticatingRealm {
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("进入CustomRealm");
        //1. 把 AuthenticationToken 转换为 UsernamePasswordToken
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        //如果设置里密码加密,此时前台传来的密码已经被加密了
        //2. 从 UsernamePasswordToken 中来获取 username
        String username = upToken.getUsername();
       
        //3. 调用数据库的方法, 从数据库中查询 username 对应的用户记录
        System.out.println("从数据库中获取 username: " + username + " 所对应的用户信息.");

        //4. 若用户不存在, 则可以抛出 UnknownAccountException 异常
        if ("unknown".equals(username)) {
            throw new UnknownAccountException("用户不存在!");
        }
        //5. 根据用户信息的情况, 决定是否需要抛出其他的 AuthenticationException 异常.
        if ("monster".equals(username)) {
            throw new LockedAccountException("用户被锁定");
        }

        //6. 根据用户的情况, 来构建 AuthenticationInfo 对象并返回. 通常使用的实现类为:        SimpleAuthenticationInfo
       
        //1). principal: 认证的实体信息. 可以是 username, 也可以是数据表对应的用户的实体类对象.
        Object principal = username;
        //2). credentials: 密码. 从数据库中获取的,先写死
        Object credentials =123 ; 
     
        //3). realmName: 当前 realm 对象的 name. 调用父类的 getName() 方法即可
        String realmName = getName();
      
         // shiro 为我们做一个密码的比对 credentials 和 upToken (中的密码)进行比对
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, realmName);
      
        return info;

    }
    
}

由于shiroFilter会拦截from表单的提交请求,所以我们要在shiroFilter对登录请求放开,让其可以匿名访问

 @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        
        ....
           Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
              filterChainDefinitionMap.put("/shiro/login", "anon");
              //用户退出
              filterChainDefinitionMap.put("/shiro/logout", "logout");
    }

list.jsp 用户登录成功后的页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
list page
   <!--用户退出 ,用户登录后,不进行退出操作 ,回退到登录界面,这时密码不正确也会登录成功,所以当用户正常退出,需要有一个登出请求   -->
<a href="shiro/logout">logout</a>
    <!-- 登出请求被shiroFilter拦截到,然后匹配到url,过滤器名称位logout,shiro位会为我们做用户退出-->
</body>
</html>

测试:

来到login.jsp页面

用户名输入 unknown 或 monster 会被捕获异常 ,密码不是123 ,登录也会失败,重定向到login.jsp,可以查看控制台的信息。

器名称位logout,shiro位会为我们做用户退出–>

```

测试:

来到login.jsp页面

用户名输入 unknown 或 monster 会被捕获异常 ,密码不是123 ,登录也会失败,重定向到login.jsp,可以查看控制台的信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值