4.Shiro认证分析和流程及实现

1.shiro认证的全过程

 

1. 获取当前的 Subject. 调用 SecurityUtils.getSubject();
2. 测试当前的用户是否已经被认证. 即是否已经登录. 调用 Subject 的 isAuthenticated() 
3. 若没有被认证, 则把用户名和密码封装为 UsernamePasswordToken 对象
   1). 创建一个表单页面
   2). 把请求提交到 SpringMVC 的 Handler
   3). 获取用户名和密码. 
4. 执行登录: 调用 Subject 的 login(AuthenticationToken) 方法. 
5. 自定义 Realm 的方法, 从数据库中获取对应的记录, 返回给 Shiro.
   1). 实际上需要继承 org.apache.shiro.realm.AuthenticatingRealm 类
   2). 实现 doGetAuthenticationInfo(AuthenticationToken) 方法. 
6. 由 shiro 完成对密码的比对. 

2.shiro认证Realm部分代码

(1)表单(这里表单url请求必须要有权限,没有就去application.xml设置:/shiro/login = anon)

 <form action="shiro/login" method="post">
   
       用户名:<input type="text" name="username"/>
       <br><br>
        密码:	<input type="password" name="password">
        <br><br>
        <input type="submit" value="submit" />
   </form>

(2)后台controller

package com.yang.shiro.realm;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

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

	private static final transient Logger log = LoggerFactory.getLogger(ShiroHandle.class);
	
	@RequestMapping("/login")
	public String login(@RequestParam("username") String username,
			@RequestParam("password") String password) {
		
		 // 获取当前的 Subject. 调用 SecurityUtils.getSubject();
        Subject currentUser = SecurityUtils.getSubject();
     // let's login the current user so we can check against roles and permissions:
        // 测试当前的用户是否已经被认证. 即是否已经登录. 
        // 调动 Subject 的 isAuthenticated() 
        if (!currentUser.isAuthenticated()) {
        	// 把用户名和密码封装为 UsernamePasswordToken 对象
            UsernamePasswordToken token = new UsernamePasswordToken("username", "password");
            // rememberme
            token.setRememberMe(true);
            try {
            	System.out.println("1:"+token.hashCode());
            	// 执行登录. 
                currentUser.login(token);
            } 
            // 所有认证时异常的父类. 
            catch (AuthenticationException ae) {
                System.out.println("登录失败!");
            }
        }
		return "redirect:/list.jsp";
		
	}
}

3.把提交的token传递给Realm

package com.yang.shiro.realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.realm.AuthenticatingRealm;

public class ShiroRealm extends AuthenticatingRealm {

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// TODO Auto-generated method stub
		System.out.println("2:"+token.hashCode());
		System.out.println("token:"+token);
		//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 = "123456";
		//(3)realmName:当前realm对象的name,调用父类的getName()方法即可
		String realmName = getName();
		System.out.println("realmName:" + realmName);
		SimpleAuthenticationInfo  info = new SimpleAuthenticationInfo(principal, 
                                                              credentials, realmName); 
		return info;
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值