Laravel:在自定义登录中集成Throttle

时间:2017-07-19 03:36:41

标签: php laravel validation laravel-5.4 throttling

如果我没有使用laravel给出的默认LoginController,如何集成laravel throttle?

这是我的控制器:

  use AuthenticatesUsers;

  //function for login
  public function login(Request $requests){
    $username = $requests->username;
    $password = $requests->password;

    /**to login using email or username**/
    if(filter_var($username, FILTER_VALIDATE_EMAIL)) {

      Auth::attempt(['email' => $username, 'password' => $password]);
    } else {

      Auth::attempt(['username' => $username, 'password' => $password]);
    }


    if(Auth::check()){
      if(Auth::user()->type_user == 0){

        return view('users.dashboard');

      }
      else{
        return view('admin.dashboard');
      }
    }
    else{

      return Redirect::back()->withInput()->withErrors(['message'=>$login_error],'login');

    }
  }

我想限制失败的登录,但我似乎无法使用我自己的控制器。你能帮帮我吗?

7 个答案:

答案 0 :(得分:3)

在方法中添加以下代码。把它作为第一件事

let page_number_array = [1,2,3,4,5];

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      currentPage: 1
    }
  }
  pageNumberClicked = num => {
    this.setState({
      currentPage: num
    });
  }
  getPreviousPage = () => {
    this.setState({
      currentPage: this.state.currentPage - 1 > 0 ? this.state.currentPage - 1 : 1
    });
  }
  getNextPage = () => {
    this.setState({
      currentPage: this.state.currentPage + 1 <= page_number_array.length ? this.state.currentPage + 1 : 1
    });
  }
  render() {
    return (
      <div className="pagination-media">
        <a href="#" onClick={this.getPreviousPage} className="text-success">
          <span className="fa fa-chevron-left"></span> 
          &nbsp;PREV
        </a> &nbsp;
            {page_number_array.map((item, i) => (
              <a 
                href="#" 
                id={`page-${item}`} 
                className={`${this.state.currentPage === item ? 'text-success' : ''} page-no-m`}
                onClick={() => this.pageNumberClicked(item)}
              >
                {`${item} `}
              </a>
             ))}
              &nbsp;
                <a href="#" onClick={this.getNextPage}
                  className="text-success">
                    <b>NEXT</b> &nbsp;
                    <span className="fa fa-chevron-right"></span>
                </a>
              </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'));

现在添加以下代码,其中登录失败。这将增加失败的尝试次数。

.text-success {
  color: green;
}

成功登录后,添加以下代码以便重置。

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

答案 1 :(得分:1)

使用Illuminate \ Foundation \ Auth中的Trait ThrottlesLogins并覆盖下面提到的2个函数。我在Laravel 5.6上进行了测试并且工作正常。

public function maxAttempts()
{
    //Lock out on 5th Login Attempt
    return 5;
}

public function decayMinutes()
{
    //Lock for 1 minute
    return 1;
}

答案 2 :(得分:1)

尝试将限制添加到控制器的构造函数中,如下所示:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

public class JsonApp {

    private static final String json = "{\"A\" : 1.0 ,\"B\" : \"X\"}";

    private static final int MAX = 1_000_000;

    private static List<List<Duration>> values = new ArrayList<>();

    static {
        IntStream.range(0, 4).forEach(i -> values.add(new ArrayList<>()));
    }

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 10; i++) {
            int v = 0;
            values.get(v++).add(defaultGson());
            values.get(v++).add(gsonAdapter());
            values.get(v++).add(defaultJackson());
            values.get(v).add(jacksonJsonFactory());
        }
        values.forEach(list -> {
            list.forEach(d -> System.out.print(d.toMillis() + " "));
            System.out.println(" avg " + list.stream()
                    .mapToLong(Duration::toMillis)
                    .average().getAsDouble());
        });
    }

    static Duration defaultGson() {
        Gson gson = new Gson();

        long start = System.nanoTime();
        for (int i = MAX; i > 0; i--) {
            gson.fromJson(json, Pojo.class);
        }

        return Duration.ofNanos(System.nanoTime() - start);
    }

    static Duration gsonAdapter() throws IOException {
        PojoTypeAdapter adapter = new PojoTypeAdapter();

        long start = System.nanoTime();
        for (int i = MAX; i > 0; i--) {
            adapter.fromJson(json);
        }

        return Duration.ofNanos(System.nanoTime() - start);
    }

    static Duration defaultJackson() throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

        long start = System.nanoTime();
        for (int i = MAX; i > 0; i--) {
            mapper.readValue(json, Pojo.class);
        }

        return Duration.ofNanos(System.nanoTime() - start);
    }

    static Duration jacksonJsonFactory() throws IOException {
        JsonFactory jfactory = new JsonFactory();

        long start = System.nanoTime();
        for (int i = MAX; i > 0; i--) {
            readPartially(jfactory);
        }
        return Duration.ofNanos(System.nanoTime() - start);
    }

    static Pojo readPartially(JsonFactory jfactory) throws IOException {
        try (JsonParser parser = jfactory.createParser(json)) {

            Pojo pojo = new Pojo();

            parser.nextToken(); // skip START_OBJECT - {
            parser.nextToken(); // skip A name
            parser.nextToken();
            pojo.A = parser.getDoubleValue();
            parser.nextToken(); // skip B name
            parser.nextToken();
            pojo.B = parser.getValueAsString();

            return pojo;
        }
    }
}

class PojoTypeAdapter extends TypeAdapter<Pojo> {

    @Override
    public void write(JsonWriter out, Pojo value) {
        throw new IllegalStateException("Implement me!");
    }

    @Override
    public Pojo read(JsonReader in) throws IOException {
        if (in.peek() == com.google.gson.stream.JsonToken.NULL) {
            in.nextNull();
            return null;
        }

        Pojo pojo = new Pojo();

        in.beginObject();
        in.nextName();
        pojo.A = in.nextDouble();
        in.nextName();
        pojo.B = in.nextString();

        return pojo;
    }
}

class Pojo {

    double A;
    String B;

    @Override
    public String toString() {
        return "Pojo{" +
                "A=" + A +
                ", B='" + B + '\'' +
                '}';
    }
}

不幸的是,Laravel文档没有对节流说太多: https://laravel.com/docs/6.x/authentication#login-throttling

但是,字符串的/** * Create a new login controller instance. * * @return void */ public function __construct() { $this->middleware('throttle:3,1')->only('login'); } 部分最多对应3次尝试,衰减时间为1分钟。

3,1可以在throttle数组的/project-root/laravel/app/Http/Kernel.php中定义,如下所示:
routeMiddleware。 Laravel文档在此处说明了此方法:https://laravel.com/docs/6.x/middleware#assigning-middleware-to-routes

答案 3 :(得分:0)

路线::帖子(&#39;登录&#39;,[&#39;之前&#39; =&gt;&#39;油门:2,60&#39;,&#39;使用&#39; =&gt;&#39; YourLoginController @ Login&#39;]);

答案 4 :(得分:0)

if ($this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return redirect()->route('login')->with('alert-warning', 'Too many login attempts');
        }

protected function hasTooManyLoginAttempts(Request $request)
{
   $maxLoginAttempts = 3;

   $lockoutTime = 1; // In minutes

   return $this->limiter()->tooManyAttempts(
       $this->throttleKey($request), $maxLoginAttempts, $lockoutTime
   );
}

答案 5 :(得分:0)

试试我的版本:

use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller{
use AuthenticatesUsers;
public function login(Request $request){
    if($this->hasTooManyLoginAttempts($request)){
        $this->fireLockoutEvent($request);
        return $this->sendLockoutResponse($request);
    }else{
        if (Auth::attempt(['username' => $request->login_username, 'password' => $request->login_password])) {
        session()->put(['username'=>Auth::user()->username,'userid'=>Auth::user()->id]);
        return redirect()->intended('anydashboard');
        }else{
            $this->incrementLoginAttempts($request);
            //my '/' path is the login page, with customized response msg...
            return redirect('/')->with(['illegal'=>'Login failed, please try again!'])->withInput($request->except('password'));
        }
    }
}
}

为了使用Eloquent Model Auth(默认),你的AUTH_MODEL应该实现AuthenticatableContract,所以仔细检查你的模型:

namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract,CanResetPasswordContract
{
use Authenticatable, CanResetPassword;
//protected $fillable = [];
...
}

答案 6 :(得分:0)

虽然,这个答案很晚,但是这里,我做了什么,并且它有效。我希望它对你也有帮助。我正在使用laravel 5.2。

<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\MessageBag;
use Cookie;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;

class UserController extends Controller
{
/** Add This line on top */
use AuthenticatesAndRegistersUsers,ThrottlesLogins;
/** This way, you can control the throttling */
protected $maxLoginAttempts=3;
protected $lockoutTime=300;

public function postUserSignIn(Request $request)
{
    /** This line should be in the start of method */
    if ($this->hasTooManyLoginAttempts($request)) {
        $this->fireLockoutEvent($request);
        return $this->sendLockoutResponse($request);
    }
    /** Validate the input */
    $validation = $this->validate($request,[
        'email' => 'required|email',
        'password' => 'required|min:4'
    ]);

    /** Validation is done, now login user */
    //else to user profile
    $check = Auth::attempt(['email' => $request['email'],'password' => $request['password']]);

    if($check){

        $user = Auth::user();
        /** Since Authentication is done, Use it here */
        $this->clearLoginAttempts($request);
        if ($user->role == 1 || $user->role == 2){
            if(Session::has('cart')){
                return redirect()->route('cart');
            }
            return redirect()->intended();
        }elseif($user->role == 99) {
            return redirect()->route('dashboard');
        }

    }else{
        /** Authentication Failed */
        $this->incrementLoginAttempts($request);
        $errors = new MessageBag(['password' => ['Email and/or Password is invalid']]);
        return redirect()->back()->withErrors($errors);
    }

}

}

相关问题