@Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws ExcessiveAttemptsException { String username = (String)token.getPrincipal(); AtomicInteger retryCount = passwordRetryCache.get(username); if(retryCount == null) { retryCount = new AtomicInteger(0); passwordRetryCache.put(username, retryCount); } if(retryCount.incrementAndGet() > retryMax) { throw new ExcessiveAttemptsException("您已连续错误达" + retryMax + "次!请10分钟后再试"); } boolean matches = super.doCredentialsMatch(token, info); if(matches) { passwordRetryCache.remove(username); }else { throw new IncorrectCredentialsException("密码错误,已错误" + retryCount.get() + "次,最多错误" + retryMax + "次"); } return true; }
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String userName = (String)token.getPrincipal(); final String key = REDIS_KEY_PREFIX + userName; long maxRetry = redisTemplate.opsForValue().increment(key, 1); if(maxRetry == 1){ //首次输入密码 redisTemplate.expire(key, passwordRetryWaitMinutes, TimeUnit.MINUTES); } if(maxRetry >= passwordRetryLimit){ throw new ExcessiveAttemptsException(passwordRetryLimit + ""); } boolean matches = super.doCredentialsMatch(token, info); if(matches) { redisTemplate.delete(key); } return matches; }
@Override public boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { AuthenticationToken token = createToken(request, response); if (token == null) { String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken " + "must be created in order to execute a login attempt."; throw new IllegalStateException(msg); } if (checkIfAccountLocked(request)) { return onLoginFailure(token, new ExcessiveAttemptsException(), request, response); } else { if (!doLogin(request, response, token)) { resetAccountLock(getUsername(request)); return false; } return true; } }
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info){ String username = (String) token.getPrincipal(); Element element = passwordRetryCache.get(username); if(element == null){ element = new Element(username, new AtomicInteger(0)); passwordRetryCache.put(element); } AtomicInteger retryCount = (AtomicInteger) element.getObjectValue(); if(retryCount.incrementAndGet() > 5){ throw new ExcessiveAttemptsException(); } boolean matches = super.doCredentialsMatch(token, info); if(matches){ passwordRetryCache.remove(username); } return matches; }
@Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { if (token instanceof UsernamePasswordToken) { String username = ((UsernamePasswordToken) token).getUsername(); AtomicInteger retryCount = passwordRetryCache.get(username); if (retryCount == null) { retryCount = new AtomicInteger(0); passwordRetryCache.put(username, retryCount); } if (retryCount.incrementAndGet() > maxRetryCount) { throw new ExcessiveAttemptsException(); } boolean matched = super.doCredentialsMatch(token, info); if (matched) { passwordRetryCache.remove(username); } return matched; } return super.doCredentialsMatch(token, info); }
@Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String username = (String) token.getPrincipal(); // retry count + 1 if (passwordRetryCache != null) { AtomicInteger retryCount = passwordRetryCache.get(username); if (retryCount == null) { retryCount = new AtomicInteger(0); passwordRetryCache.put(username, retryCount); } if (retryCount.incrementAndGet() > 5) { // if retry count > 5 throw throw new ExcessiveAttemptsException(); } } boolean matches = super.doCredentialsMatch(token, info); if (matches && passwordRetryCache != null) { // clear retry count passwordRetryCache.remove(username); } return matches; }
@Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String username = (String) token.getPrincipal(); //retry count + 1 AtomicInteger retryCount = (AtomicInteger) SilentGo.me().getConfig().getCacheManager().get("passwordRetryCache", username); if (retryCount == null) { retryCount = new AtomicInteger(0); SilentGo.me().getConfig().getCacheManager().set("passwordRetryCache", username, retryCount); } if (retryCount.incrementAndGet() > 5) { //if retry count > 5 throw throw new ExcessiveAttemptsException(); } boolean matches = super.doCredentialsMatch(token, info); if (matches) { //clear retry count SilentGo.me().getConfig().getCacheManager().evict("passwordRetryCache", username); } return matches; }
public boolean doCredentialsMatch(final AuthenticationToken token, final AuthenticationInfo info) { Object _principal = token.getPrincipal(); final String username = ((String) _principal); AtomicInteger retryCount = this.passwordRetryCache.get(username); boolean _equals = Objects.equal(retryCount, null); if (_equals) { AtomicInteger _atomicInteger = new AtomicInteger(0); retryCount = _atomicInteger; this.passwordRetryCache.put(username, retryCount); } int _incrementAndGet = retryCount.incrementAndGet(); boolean _greaterThan = (_incrementAndGet > 5); if (_greaterThan) { throw new ExcessiveAttemptsException(); } final boolean matches = super.doCredentialsMatch(token, info); if (matches) { this.passwordRetryCache.remove(username); } return matches; }
@Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String username = (String)token.getPrincipal(); //retry count + 1 AtomicInteger retryCount = passwordRetryCache.get(username); if(retryCount == null) { retryCount = new AtomicInteger(0); passwordRetryCache.put(username, retryCount); } if(retryCount.incrementAndGet() > 5) { //if retry count > 5 throw throw new ExcessiveAttemptsException(); } boolean matches = super.doCredentialsMatch(token, info); if(matches) { //clear retry count passwordRetryCache.remove(username); } return matches; }
@Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String username = (String) token.getPrincipal(); // retry count + 1 AtomicInteger retryCount = faultPasswordCache.get(username); if (null == retryCount) { retryCount = new AtomicInteger(0); faultPasswordCache.put(username, retryCount); } if (retryCount.incrementAndGet() > 5) { // if retry count > 5 throw throw new ExcessiveAttemptsException(); } boolean matches = super.doCredentialsMatch(token, info); if (matches) { // clear retry count faultPasswordCache.remove(username); } return matches; }
@Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String username = (String)token.getPrincipal(); AtomicInteger retryCount = passwordRetryCache.get(username); if (retryCount == null) { retryCount = new AtomicInteger(0); passwordRetryCache.put(username, retryCount); } if (retryCount.incrementAndGet() > 10) { throw new ExcessiveAttemptsException("您重试密码超过10次,账号已被锁定!"); } boolean matches = super.doCredentialsMatch(token, info); if (matches) { passwordRetryCache.remove(username); } return matches; }
@Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String username = (String)token.getPrincipal(); //retry count + 1 AtomicInteger retryCount = passwordRetryCache.get(username); if(retryCount == null) { retryCount = new AtomicInteger(0); passwordRetryCache.put(username, retryCount); } if(retryCount.incrementAndGet() > 5) { //if retry count > 5 throw throw new ExcessiveAttemptsException("您已连续5次密码输入错误,请过1小时之后再重试!"); } boolean matches = super.doCredentialsMatch(token, info); if(matches) { //clear retry count passwordRetryCache.remove(username); } return matches; }
/** * 用户登录 * @return */ @MumuLog(name = "用户登录",operater = "POST") @RequestMapping(value = "/login",method = {RequestMethod.POST}) public ModelAndView logining(HttpServletRequest request){ String exceptionClassName = (String) request.getAttribute("shiroLoginFailure"); String error = null; if (UnknownAccountException.class.getName().equals(exceptionClassName)) { error = "用户名/密码错误"; } else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) { error = "用户名/密码错误"; } else if(ExcessiveAttemptsException.class.getName().equals(exceptionClassName)){ error = "输入错误次数太过,请稍后重试"; } else if(DisabledAccountException.class.getName().equals(exceptionClassName)){ error="账户被锁定,请联系管理员"; }else if(AccountUnActiveException.class.getName().equals(exceptionClassName)){ error="账户未激活,请登录邮箱激活账号!"; }else if (exceptionClassName != null) { error = "错误提示:" + exceptionClassName; } Map<String,String> map=new HashMap<String,String>(); if(error!=null){ request.setAttribute("shiroLoginFailure", error); map.put("code","500"); map.put("msg","failure"); map.put("data",error); return new ModelAndView("login",map); } map.put("code","200"); map.put("msg","success"); map.put("data","登录成功"); return new ModelAndView("redirect:/system/index",map); }
/** * 做认证匹配 */ @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { //获取缓存key String loginName=(String) token.getPrincipal(); String cacheName=getCacheName(loginName); // retry count + 1 String retryCount=jedisClient.get(cacheName); if (retryCount == null) { //缓存两小时 jedisClient.incr(cacheName); jedisClient.expire(cacheName,60*60*2); }else{ int counter=Integer.parseInt(retryCount); if(counter<5){ jedisClient.incr(cacheName); }else{ throw new ExcessiveAttemptsException(); } } if(loginCredentialsHandler!=null){ loginCredentialsHandler.before(); } boolean matches = super.doCredentialsMatch(token, info); if (matches) { // clear retry count jedisClient.del(cacheName); //用户认证成功之后 进行相关操作 if(loginCredentialsHandler!=null){ loginCredentialsHandler.after(); } }else{ SysUser unloginUser=new SysUser(); unloginUser.setUserName(loginName); unloginUser.setPassword(token.getCredentials().toString()); SecurityUtils.getSubject().getSession(true).setAttribute(SysUser.SYS_USER, unloginUser); } return matches; }
@Test(expected = ExcessiveAttemptsException.class) public void testRetryLimitHashedCredentialsMatcherWithMyRealm(){ for (int i = 1; i <= 5; i++) { try { login("classpath:shiro-retryLimitHashedCredentialsMatcher.ini", "liu", "1234"); } catch (Exception e){ //前五次会抛出IncorrectCredentialsException,忽略掉 } } login("classpath:shiro-retryLimitHashedCredentialsMatcher.ini", "liu", "1234"); }
/** * 增加重试次数限制,验证方法不改变 * @param token * @param info * @return */ @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String username = (String) token.getPrincipal(); //retry count + 1 Element element = passwordRetryCache.get(username); if(element == null){ element = new Element(username, new AtomicInteger(0)); passwordRetryCache.put(element); } AtomicInteger retryCount = (AtomicInteger) element.getObjectValue(); if(retryCount.incrementAndGet() > 5){ throw new ExcessiveAttemptsException(); } //验证还是调用父类的,不改变 boolean matches = super.doCredentialsMatch(token, info); if(matches){ // clear retry count passwordRetryCache.remove(username); } return matches; }
@Test(expected = ExcessiveAttemptsException.class) public void testLoginFailWithLimitRetryCount() { for(int i = 1; i <= 5; i++) { try { login("classpath:shiro.ini", u3.getUsername(), password + "1"); } catch (Exception e) { /*ignore*/ } } login("classpath:shiro.ini", u3.getUsername(), password + "1"); //需要清空缓存,否则后续的执行就会遇到问题(或者使用一个全新账户测试) }
@Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { boolean matches = false; String username = (String)token.getPrincipal(); Integer retryCount = hashOps.get(keyPrefix+Constants.UNDERLINE+username, username); if(retryCount == null) { retryCount = new Integer(0); } retryCount += 1; hashOps.put(keyPrefix+Constants.UNDERLINE+username, username, retryCount); if(retryCount > maxAttemptLoginTimes) { //if retry count > maxAttemptLoginTimes throw log.warn("username: " + username + " tried to login more than "+maxAttemptLoginTimes+" times in period"); //after maxAttemptLoginFreezeMinutes, user can retry login redisTemplate.expire(keyPrefix+Constants.UNDERLINE+username, maxAttemptLoginFreezeMinutes, TimeUnit.MINUTES); throw new ExcessiveAttemptsException(); }else{ matches = super.doCredentialsMatch(token, info); if(matches) { //clear retry count if(hashOps.hasKey(keyPrefix+Constants.UNDERLINE+username, username)){ hashOps.delete(keyPrefix+Constants.UNDERLINE+username,username); } } } return matches; }
/** * 前后端分离的情况之下rest风格登录获取TGT ST * @Description:TODO * @author:hsj qq:2356899074 * @time:2017年12月1日 下午2:49:40 * @param req * @param respon * @return * @throws Exception */ @RequestMapping("/restlogin") public String restlogin(HttpServletRequest req,HttpServletResponse respon)throws Exception{ // return RestFulLogin.validateFromCAS("hsjhsj", "hsjhsj"); //校验有没有username和password String username = "hsjhsj"; UsernamePasswordToken token = new UsernamePasswordToken("hsjhsj","hsjhsj"); //获取当前的Subject Subject currentUser = SecurityUtils.getSubject(); try { //在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查 //每个Realm都能在必要时对提交的AuthenticationTokens作出反应 //所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法 logger.info("对用户[" + username + "]进行登录验证..验证开始"); currentUser.login(token); logger.info("对用户[" + username + "]进行登录验证..验证通过"); }catch(UnknownAccountException uae){ logger.info("对用户[" + username + "]进行登录验证..验证未通过,未知账户"); return "403"; }catch(IncorrectCredentialsException ice){ logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证"); return "403"; }catch(LockedAccountException lae){ logger.info("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定"); return "403"; }catch(ExcessiveAttemptsException eae){ logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多"); return "403"; }catch(AuthenticationException ae){ //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景 logger.info("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下"); ae.printStackTrace(); return "403"; } //验证是否登录成功 if(currentUser.isAuthenticated()){ logger.info("用户[" + username + "]登录认证通过(这里可以进行一些认证通过后的一些系统参数初始化操作)"); return "inde"; }else{ token.clear(); return "403"; } }
@RequestMapping(value="/login", method=RequestMethod.POST) public String login(String username, String password, HttpServletRequest request){ System.out.println("-------------------------------------------------------"); String rand = (String)request.getSession().getAttribute("rand"); String captcha = WebUtils.getCleanParam(request, "captcha"); System.out.println("用户["+username+"]登录时输入的验证码为["+captcha+"],HttpSession中的验证码为["+rand+"]"); if(!StringUtils.equals(rand, captcha)){ request.setAttribute("message_login", "验证码不正确"); return InternalResourceViewResolver.FORWARD_URL_PREFIX + "/"; } UsernamePasswordToken token = new UsernamePasswordToken(username, password); token.setRememberMe(true); System.out.print("为验证登录用户而封装的Token:"); System.out.println(ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE)); //获取当前的Subject Subject currentUser = SecurityUtils.getSubject(); try { //在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查 //每个Realm都能在必要时对提交的AuthenticationTokens作出反应 //所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法 System.out.println("对用户[" + username + "]进行登录验证...验证开始"); currentUser.login(token); System.out.println("对用户[" + username + "]进行登录验证...验证通过"); }catch(UnknownAccountException uae){ System.out.println("对用户[" + username + "]进行登录验证...验证未通过,未知账户"); request.setAttribute("message_login", "未知账户"); }catch(IncorrectCredentialsException ice){ System.out.println("对用户[" + username + "]进行登录验证...验证未通过,错误的凭证"); request.setAttribute("message_login", "密码不正确"); }catch(LockedAccountException lae){ System.out.println("对用户[" + username + "]进行登录验证...验证未通过,账户已锁定"); request.setAttribute("message_login", "账户已锁定"); }catch(ExcessiveAttemptsException eae){ System.out.println("对用户[" + username + "]进行登录验证...验证未通过,错误次数过多"); request.setAttribute("message_login", "用户名或密码错误次数过多"); }catch(AuthenticationException ae){ //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景 System.out.println("对用户[" + username + "]进行登录验证...验证未通过,堆栈轨迹如下"); ae.printStackTrace(); request.setAttribute("message_login", "用户名或密码不正确"); } //验证是否登录成功 if(currentUser.isAuthenticated()){ System.out.println("用户[" + username + "]登录认证通过(这里可进行一些认证通过后的系统参数初始化操作)"); return "main"; }else{ token.clear(); return InternalResourceViewResolver.FORWARD_URL_PREFIX + "/"; } }
@SuppressWarnings({ "rawtypes", "unchecked" }) @RequestMapping(value = "/login") public ModelAndView login(String username, String password) { Map map = new HashMap<String, String>(); ModelAndView mav = new ModelAndView(); if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) { map.put("status", "faied"); map.put("msg", "用户名和密码不能为空"); mav.addObject("detail", map); return mav; } UsernamePasswordToken token = new UsernamePasswordToken(username, password); SecurityUtils.setSecurityManager(securityManager); Subject subject = SecurityUtils.getSubject(); try { subject.login(token); } catch (IncorrectCredentialsException ice) { // 捕获密码错误异常 map.put("status", "failed"); map.put("msg", "密码错误"); mav.addObject("detail", map); return mav; } catch (UnknownAccountException uae) { // 捕获未知用户名异常 map.put("status", "failed"); map.put("msg", "用户不存在"); mav.addObject("detail", map); return mav; } catch (ExcessiveAttemptsException eae) { // 捕获错误登录过多的异常 map.put("status", "failed"); map.put("msg", "请稍后再试"); mav.addObject("detail", map); return mav; } map.put("status", "success"); map.put("msg", "登录成功"); mav.addObject("detail", map); return mav; }
@RequestMapping(value="/login",method=RequestMethod.POST) public String login(@Valid User user,BindingResult bindingResult,RedirectAttributes redirectAttributes){ if(bindingResult.hasErrors()){ return "login"; } String username = user.getUsername(); UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword()); //获取当前的Subject Subject currentUser = SecurityUtils.getSubject(); try { //在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查 //每个Realm都能在必要时对提交的AuthenticationTokens作出反应 //所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法 logger.info("对用户[" + username + "]进行登录验证..验证开始"); currentUser.login(token); logger.info("对用户[" + username + "]进行登录验证..验证通过"); }catch(UnknownAccountException uae){ logger.info("对用户[" + username + "]进行登录验证..验证未通过,未知账户"); redirectAttributes.addFlashAttribute("message", "未知账户"); }catch(IncorrectCredentialsException ice){ logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证"); redirectAttributes.addFlashAttribute("message", "密码不正确"); }catch(LockedAccountException lae){ logger.info("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定"); redirectAttributes.addFlashAttribute("message", "账户已锁定"); }catch(ExcessiveAttemptsException eae){ logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多"); redirectAttributes.addFlashAttribute("message", "用户名或密码错误次数过多"); }catch(AuthenticationException ae){ //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景 logger.info("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下"); ae.printStackTrace(); redirectAttributes.addFlashAttribute("message", "用户名或密码不正确"); } //验证是否登录成功 if(currentUser.isAuthenticated()){ logger.info("用户[" + username + "]登录认证通过(这里可以进行一些认证通过后的一些系统参数初始化操作)"); return "redirect:/user"; }else{ token.clear(); return "redirect:/login"; } }
@Override public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username" ); String password = req.getParameter("password" ); UsernamePasswordToken token = new UsernamePasswordToken(username, password); logger.info( "Doing login for user: " + username ); Subject currentUser = SecurityUtils.getSubject(); try { currentUser.login(token); } catch ( UnknownAccountException uae ) { logger.warn( "Failing login with 401:", uae ); resp.sendError(405); return; } catch ( IncorrectCredentialsException ice ) { logger.warn( "Failing login with 401:", ice ); resp.sendError(405); return; } catch ( LockedAccountException lae ) { logger.warn( "Failing login with 401:", lae ); resp.sendError(401); return; } catch ( ExcessiveAttemptsException eae ) { logger.warn( "Failing login with 401:", eae ); resp.sendError(401); return; } catch ( AuthenticationException ae ) { logger.warn( "Failing login with 401:", ae ); resp.sendError(401); return; } if( currentUser.hasRole("ShiroUsersRole") ) { try { Cookie authTokenCookie = new Cookie("authToken", AuthToken.generateToken(configProps)); resp.addCookie(authTokenCookie); // resp.setStatus(HttpServletResponse.SC_OK); resp.sendRedirect( "/withsocket.jsp" ); } catch( Exception e ) { logger.error( "Failed creating authToken cookie.", e ); resp.sendError( 500 ); return; } } else { logger.error("User does not have required role!"); resp.sendError(401); return; } }