一.从应用程序的角度观察Shiro是如何完成工作!
二.认证的步骤:
1.获取当前的Subject .调用SecurityUtils.getSubject();
2.测试当前的用户是否已经认证,即是否已登录,调用Subject的isAuthenticated()
3.若没有被认证,则把用户名和密码封装为UsernamePaswordToken对象
1)创建一个表单页面
2)把请求提交到SpringMVC 的Handler
3)获取用户名和密码
4.执行登录:调用Subject的login(AuthenticationToken)方法.
5.自定义Realm的方法,从数据库中获取对应的记录,返回给Shiro.
1)实际上需要继承org.apache.shiro.realm.AuthenticatingRealm抽象类
2)实现这个类中的doGetAuthenticationInfo(AuthenticationToken token)方法;
6.由 Shiro完成密码的比对哦!
三.具体如下:
在Shiro 集成Spring详细介绍(四)基础上扩展哦!
login.jsp页面
<h1>Login JSP!</h1>
<form action="shiro/login" method="post">
name:<input type="text" name="uname"/><p/>
pass:<input type="password" name="upwd"/><p/>
<input type="submit" value="login" name="sub"/>
</form>
ShiroHandler类
@Controller
@RequestMapping("/shiro")
public class ShiroHandler {
@RequestMapping("/login")
public String login(@RequestParam("uname") String uname,@RequestParam("upwd") String upwd){
// 1.获取当前的Subject .调用SecurityUtils.getSubject();
Subject currentUser=SecurityUtils.getSubject();
// 2.测试当前的用户是否已经认证,即是否已登录,调用Subject的isAuthenticated()
if(!currentUser.isAuthenticated()){
//将用户名和密码封装在UsernamePasswordToken对象中
UsernamePasswordToken token=new UsernamePasswordToken(uname, upwd);
//记住哦
token.setRememberMe(true);
try {
//可以执行hashCode
System.out.println("token==>"+token.hashCode());
//执行登录
currentUser.login(token);
} catch (AuthenticationException e) {
// TODO: handle exception
System.out.println("登录失败:"+e.getMessage());
}
}
return "redirect:/list.jsp";
}
}
ShiroRealm类
public class ShiroRealm extends AuthenticatingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// TODO Auto-generated method stub
System.out.println("doGetAuthenticationInfo==>"+token.hashCode());
return null
}
application.xml文件
启动运行:
原因:请求的token与ShiroRealm中的token hashCode是相同;但在ShiroRealm中没有写代码实现哦!
ShiroRealm实现如下:
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// TODO Auto-generated method stub
// System.out.println("doGetAuthenticationInfo==>"+token.hashCode());
// 1.把AuthenticationToken转换成UsernamePasswordToken
UsernamePasswordToken uToken = (UsernamePasswordToken) token;
// 2.从UsernamePasswordToken中取出username
String username = uToken.getUsername();
// 3.调用数据库的方法,从数据库中查询username对应的用户记录
System.out.println("从数据库中查询username:[" + username + "]对应用户记录");
// 4.若用户不存在,则可以抛出UnknowAccountException子类异常
if ("bear".equals(username)) {
throw new UnknownAccountException("用户不存在!");
}
// 5.根据用户信息情况,觉得是否需要抛出其他AuthenticationException异常
if ("angel".equals(username)) {
throw new LockedAccountException("用户被锁定!");
}
// 6.根据用户情况,来构建AuthenticationInfo对象返回,通常实现类SimpleAuthenticationInfo
// a)principal:认证实体信息,可以是username,也可以是数据库表对应的用户
Object principal = username;
// b)credentials: 密码
Object credentials = "aaa";
// c)realmName:当前realm对象的name,调用父类的getName()方法;
String realmName = getName();
// 认证对象
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, realmName);
return info;
}
运行测试如下:
(1)angel用户登录!
(2)qq用户登录!就登录成功!
那么其他页面就可以访问了!
(3)bear用户登录!
(4)如果是退回
(5)如何解决这个问题了呢? 用登出
(6)单击就ok了!重新登录哦!