Shiro过滤器&标签简介
判断 sesion中是否有 user 判断账户密码是否正确
- (1)分析
需要过滤器控制 没有权限下访问链接
需要标签控制 没有权限下 界面元素的隐藏
》anon
代表不认证也可以访问,通常对静态资源进行放行
》authc
代表必须通过认证才可以访问,通常对动态资源(controller,jsp页面)进行拦截,如果用户没有认证,Shiro会自动跳转到login.jsp页面
Shiro登录认证-判断session中的user
- (1)
过滤器
在项目中使用认证过滤器拦截资源(该拦截的拦截,该放行的放行) - (2)
authc认证过滤器
必须认证才能访问,如果未认证跳登录页 - (3)
anon过滤器
放行,不需要拦截认证 - (4)拦截路径问题
/*
/**
applicationContext-shiro.xml
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!--注入SecurityManager-->
<property name="securityManager" ref="securityManager"/>
<property name="filterChainDefinitions">
<value>
<!-- 如果请求提静态资源 anon 不要求session中有user,直接可以访问-->
/css/**=anon
/img/**=anon
/plugins/**=anon
<!-- 如果请求login.do方法 anon-->
/system/user/login-shiro.do=anon
<!-- 如果除以上之外的xxx.do 要求登录 authc 查询session中是否有user-->
/**=authc
</value>
</property>
<!--如果 session就是没有user,表示未登录,页面转到login-shiro.jsp -->
<property name="loginUrl" value="/login-shiro.jsp"/>
</bean>
Shiro登录认证-用户密码判断
Shiro登录认证三种结果
- (1)正确
无异常
User user = (User)subject.getPrincipal()
//获取user对象 - (2)用户不存在
程序抛出UnknownAccountException
异常 - (3)用户密码出错
程序抛出IncorrectCredentialsException
异常
Shiro登录认证login方法
- (1) 获取Subject对象
Subject subject = SecurityUtils.getSubject();
- (2)调用Subject的认证方法 :
login 本质:AuthRealm的认证方法
subject.login(token);
- (3)登录的结果
正确
用户不存在
用户密码出错
UserController
//${path}/system/user/login-shiro.do email,password
@RequestMapping(path = "/login-shiro",method = {RequestMethod.GET,RequestMethod.POST})
public String loginShiro(String email,String password) {
l.info("loginShiro email=" + email);
l.info("loginShiro password=" + password);
//使用shiro框架进行认证 结果也是三种可能 正确 没有异常,用户不存在 UnknownAccountException,密码出错 IncorrectCredentialsException
//本质是需要调用realm进行查找用户
//1:先获取subject 表示对securitymanager连接
Subject subject = SecurityUtils.getSubject(); //获取连接
//2:调用 securitymanager
//3:再调用realm
//验证信息
UsernamePasswordToken token = new UsernamePasswordToken(email, password);
try {
subject.login(token); //正确 --realm
l.info("密码正确");
//保存用户信息
User user = (User) subject.getPrincipal(); //获取用户 --realm
session.setAttribute("loginUser",user);
//一个 Module对象 就是左侧栏上的一个菜单项
List<Module> menus = iModuleService.findModulesByUser(user);
session.setAttribute("menus",menus);
//跳到主页
return "redirect:/home/toMain.do";
} catch (IncorrectCredentialsException e){//错误
e.printStackTrace();
l.info("密码错误");
request.setAttribute("error","账号或密码错误");
return "forward:/login-shiro.jsp";
} catch (UnknownAccountException e) {//用户不存在
e.printStackTrace();
l.info("用户不存在");
request.setAttribute("error","用户名不存在");
return "forward:/login-shiro.jsp";
}
}
AuthRealm
//认证(登录账号密码)
@Autowired
IUserService iUserService;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
l.info("AuthRealm doGetAuthenticationInfo 函数执行了");
//响应login方法和getPrincipal方法的调用
//参1 authenticationToken 接收subject.login(token);方法的值
UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken;
String email = usernamePasswordToken.getUsername();
l.info("doGetAuthenticationInfo --"+email);
//调service读dao
User user = iUserService.findUserByEmail(email);
l.info("doGetAuthenticationInfo --"+user);
if(user == null){
//用户不存在
return null; //-->系统会将null转成UnknownAccountException抛出
}else {
//存在用户
//AuthenticationInfo 返回给 User user = (User) subject.getPrincipal();
/**
* 参数一:principal,存放用户登录信息,subject.getPrincipal()获取
* 参数二:数据库的密码
* 参数三:realm的别名,只有在多个Realm的时候才会用,一般不用
*/
AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), "");
return info;
}
}