细节:
---[urls]部分配置,其格式是 url=拦截器【参数】 ,拦截器【参数】
---如果当前请求的 url 匹配 【urls】 部分或者某个url模式,将会执行配置的拦截器
---anon(anonymous)拦截器表示匿名访问(即不需要登陆验证)
---authc(authentication)拦截器的表示需要身份认证之后才能访问
<property name="filterChainDefinitions"> <value> /login.jsp = anon # everything else requires authentication: /** = authc </value> </property>
/login.jsp = anon # everything else requires authentication: /** = authc /user.jsp = anon
此时上面的会覆盖下面的user.jsp 无法访问
认证:
步骤:
1.获取当前subject,SecurityUtils.getSubject();
2.测试当前用户是否已经被认证,即是否已经登陆, currentUser.isAuthenticated()
3.若没有认证则/把用户名和密码封装为UsernamePasswordToken对象
-创建一个表单
-把请求提交到spriingmvc 的handler
-获取用户和密码
4.执行登陆 currentUser.login(token);
5.自定义Relam方法,从数据库中获取相应的记录,返回给Shiro
-实际上是需要集成org.apache.shiro.realm.AuthenticatingRealm
-实现doGetAuthenticationInfo()方法
6.有shiro完成对密码的比对
测试使用到的文件:
下面开始代码过程:
login.jsp页面的登陆标志代码:
login <form action="shiro/login" method="post"> username:<input type="text" name="username"> password:<input type="password" name="password"> <input type="submit" value="submit"> </form>
在application中
<property name="filterChainDefinitions"> <value> /login.jsp = anon /shiro/login = anon # everything else requires authentication: /** = authc </value> </property>
ShiroHandler.java
@Controller @RequestMapping("/shiro") public class ShiroHandler { @RequestMapping("/login") public String login(@RequestParam("username")String username,@RequestParam("password") String password){ Subject currentUser = SecurityUtils.getSubject(); if (!currentUser.isAuthenticated()) { //把用户名和密码封装为UsernamePasswordToken对象 UsernamePasswordToken token = new UsernamePasswordToken(username, password); token.setRememberMe(true); try { //执行登陆 currentUser.login(token); }catch (AuthenticationException ae) { System.out.println("登陆失败" + ae.getMessage()); } } 成功之后做重定向 return "redirect:/list.jsp"; } }
在applicationContext中需要扫描这个类的包
ShiroRealm.java
做登陆验证实现下面的接口即可
doGetAuthenticationInfo(AuthenticationToken arg0)的arg0是指就是UsernamePasswordToken token = new UsernamePasswordToken(username, password);
public class ShiroRealm extends AuthenticatingRealm { @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException { System.out.println("doGetAuthenticationInfo" + arg0); //1.把AuthenticationToken转为UsernamePasswordToken UsernamePasswordToken upToken = (UsernamePasswordToken) arg0; //2.从UsernamePasswordToken获取username String username = upToken.getUsername(); //3.调用数据库的方法,从数据库查询username对应的用户记录 System.out.println("从数据库中获取username:" + username); //4.若用户不存在可以抛出异常 UnKnownAccountException异常 if("unknow".equals(username)){ throw new UnknownAccountException("username 不存在"); } //5.根据用户信息的清空决定是否需要抛出其他的异常 if("monster".equals(username)){ throw new LockedAccountException("用户被锁定"); } //6.根据用户的情况来构建AuthenticationInfo并且返回 //以下信息是从数据库中获取的 //principal:认证的实体信息,可以是username,也可以是数据表对应的实体对象 Object principal = username; //credentials:密码 Object credentials = "1234"; //realmName:当前realm对象为name,调用父类的getName()方法即可 String realmName = getName(); SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, realmName); return info; } }
当我们输入密码为1234,以及其他为username(除了上图的两个)
此时我们就有权限对其他的页面进行测试
出错之后的异常还是会打印的
此时我们需要登出的操作
list.jsp
<body> list. <a href="shiro/logout">Logout</a> </body>
在applicationContext.xml文件中:
<!-- 配置那些页面需要受保护,以及访问这些页面需要的的权限 1)anon 可以被匿名访问 2)authc 必须认证即登陆后才可以访问的页面 3).logout登出 --> <property name="filterChainDefinitions"> <value> /login.jsp = anon /shiro/login = anon /shiro/logout = logout # everything else requires authentication: /** = authc </value> </property>
但我们点击这个超链接的 时候就会立马退出来到login.jsp页面中