1.Shiro介绍
Shiro解决了应用安全的四要素:
1.认证-用户身份识别
2.授权-访问控制
3.密码加密-保护或隐藏数据防止偷窥
4.会话管理
同时Shiro另外支持了一些辅助特性:如Web安全,单元测试,多线程
2.Shiro的优势
1.易于使用
2.广泛性
3.灵活性:Shiro可以工作在任何应用环境中,虽然他工作在Web,EJB和loC环境中,但他并不依赖这些环境。 Shiro即不强加任何规范,也无需过多依赖
4.Web能力:Shiro对Web应用的支持很神奇,允许你基于应用URL和Web协议创建灵活的安全策略,同时还提 供了一套控制页面输出的JSP标签库
5.可插拔:Shiro干净的API和设计模式使他可以方便的与许多其他框架进行集成,如Spring,Grails,Wicket, Tapestry,Mule,Apache Camel,Vaadin这类第三方框架无缝集成
3.核心概念
1.Subject:代表当前正在执行操作的用户,Subject代表的可以是人也可以是任何第三方系统账号。每个suject 实例都会被绑定到SercurityManger上
3.Realm:用户数据和Shiro数据交互的桥梁,比如用户身份认证,权限认证都需要使用Realm来读取数据
<!--shiro--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency>
@RequestMapping(value = "/login") public String login(String usermane,String password,Model model ){ //获得当前用户 Subject subject = SecurityUtils.getSubject(); //封装用户登陆的数据 UsernamePasswordToken token = new UsernamePasswordToken(usermane, password); token.setRememberMe(true);//设置记住我 可以不设置 try{ //执行登陆操作(执行这个操作会跳转到Realm对象的认证方法) subject.login(token); return "index"; }catch (UnknownAccountException uae){ System.out.println("户名不存在:"+token.getPrincipal()); model.addAttribute("msg","户名不存在"); return "login"; }catch (IncorrectCredentialsException ice){ System.out.println("密码不正确:"+token.getPrincipal()); model.addAttribute("msg","密码不正确"); return "login"; }catch (LockedAccountException lae){ System.out.println("用户名帐户不正确,请联系管理员解锁"+token.getPrincipal()); model.addAttribute("msg","用户名帐户不正确"); return "login"; } }
shiro三要素
ShiroFilterFactoryBean
DefaultWebSecurityManager(SecurityManager)
realm对象
创建的时候从后向前创建
1.先创建Realm对象 //创建实体类继承AuthorizingRealm重写AuthorizingRealm类的方法 public class UserRealm extends AuthorizingRealm { @Autowired private MyService myService; //授权方法 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行授权方法=======》"); SimpleAuthorizationInfo inof = new SimpleAuthorizationInfo(); Users users = (Users)SecurityUtils.getSubject().getPrincipal(); //给当前用户赋权限 inof.setStringPermissions(users.getPerms()); return inof; } //认证方法 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("执行认证方法========》"); //将AuthenticationToken转换为UsernamePasswordToken获得用户信息 UsernamePasswordToken token=(UsernamePasswordToken)authenticationToken; Users users = myService.selectAll(token.getUsername()); if(users==null){ //如果用户名不一样返回null 他会自动抛出UnknowAccountException异常 return null; } //获得当前用户的权限集合 HashSet<String> perms=myService.selectPerms(users.getId()); users.setPerms(perms); //进行密码认证,并将用户信息放入Sbject中 return new SimpleAuthenticationInfo(users, users.getPwd(),""); } }
2.创建DefaultWebSecurityManager对象并将realm对象和DefaultWebSecurityManager进行关联 @Configuration public class ShiroConfig { //创建自定义的realm对象,将他注入到bean中 @Bean public UserRealm userRealm(){ return new UserRealm(); } //创建DefaultWebSecurityManager并将realm对象和DefaultWebSecurityManager进行关联 @Bean public DefaultWebSecurityManager getDefaultWebSecurityManager(UserRealm userRealm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //进行关联 securityManager.setRealm(userRealm); return securityManager; } 3.创建ShiroFilterFactoryBean并将securityManager和ShiroFilterFactoryBean进行关联 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器关联 bean.setSecurityManager(securityManager); /** * shiro内置过滤器权限: * onon: 无需认证就可以访问 * authc: 必须认证了才能访问 * user: 必须有记住我功能才能用 * perms: 对某个资源有权限才能访问 * role: 拥有某个权限才能访问 * */ Map<String, String> filterMap = new LinkedHashMap<>(); //授权:设置权限拦截 filterMap.put("/user/add","perms[user:add]"); //设置跳转未授权页面的请求路径 bean.setUnauthorizedUrl("/unauthorized"); /* 设置请求拦截 filterMap.put("/user/add","authc"); filterMap.put("/user/update","authc");*/ filterMap.put("/user/*","authc"); //将拦截配置放入bean bean.setFilterChainDefinitionMap(filterMap); //设置登陆请求路径 bean.setLoginUrl("/index"); return bean; } }
1.获取当前用户
Subject currentUser=SecurityUtils.getSubject(); currentUser,getPrincipal();//获得当前用户的信息 currentUser.hasRole(“角色名称”);//判断是否有这个角色 currentUser.isPermitted(“权限”);//判断是否有这个权限 currentUser.logout();//注销
2.向当前用户的shiro的session中存取
Session session=currentUser.getSession(); session.setAttribute("键","值"); String value=(String)session.getAttribute(”键“);
SecurityUtils.getSubject().getPrincipal();
3.判断当前用户是否被认证
currentUser.isAuthenticated();//被认证返回true
4.根据账号密码生成token
UsernamePasswordToken token=new UsernamePasswordToken(账号,密码);//生成token token.setRememnerMe(true);//设置token记住当前用户
5.执行登陆操作
currentUser.login(token);