2017-10-16 3 views
1

최근 adonisjs 프레임 워크에서 응용 프로그램을 개발하기 시작했습니다. 나는 익스프레션을 사용할 수있는 선택권이 있었지만 구조화 된 방식 (주로 라우트 스타일)을 좋아하기 때문에 선호했다.Adonis.js RESTFUL API 해결 방법

현재 RESTFUL API를 구축하고 있지만 기본 라우팅/미들웨어/apiController (모든 API 요청을 처리 할 사용자 정의 컨트롤러) 시나리오를 파악할 수 없습니다.

Route.post('api/v1/login', 'ApiController.login') 
Route.post('api/v1/register', 'ApiController.register') 

// API Routes 
Route.group('api', function() { 

    Route.get('users', 'ApiController.getUsers') 

}).prefix('/api/v1').middlewares(['auth:api']) 

ApiController.js

'use strict' 

const User = use('App/Model/User') 
const Validator = use('Validator') 

const FAIL = 0 
const SUCCESS = 1 

class ApiController { 

    * login (request, response) { 

    let jsonResponse = {} 

    const email = request.input('email') 
    const password = request.input('password') 

    // validate form input 
    const rules = { 
     email: 'required|email', 
     password: 'required' 
    } 

    const messages = { 
     'email.required': 'Email field is required.', 
     'password.required': 'Password field is required.' 
    } 

    const validation = yield Validator.validateAll(request.all(), rules, messages) 

    if (validation.fails()) { 

     jsonResponse.status = FAIL 
     jsonResponse.response = {} 
     jsonResponse.response.message = validation.messages()[0].message 

    } else { 

     try { 

     yield request.auth.attempt(email, password) 

     const user = yield User.findBy('email', email) 

     const token = yield request.auth.generate(user) 

     jsonResponse.status = SUCCESS 
     jsonResponse.response = {} 
     jsonResponse.response.message = "Logged In Successfully" 
     jsonResponse.response.user = user 
     jsonResponse.response.token = token 

     } catch (e) { 

     jsonResponse.status = FAIL 
     jsonResponse.response = {} 
     jsonResponse.response.message = e.message 

     } 

    } 

    return response.json(jsonResponse) 

    } 

} 

module.exports = ApiController 

설정/auth.js

'use strict' 

const Config = use('Config') 

module.exports = { 

    /* 
    |-------------------------------------------------------------------------- 
    | Authenticator 
    |-------------------------------------------------------------------------- 
    | 
    | Authenticator is a combination of HTTP Authentication scheme and the 
    | serializer to be used for retrieving users. Below is the default 
    | authenticator to be used for every request. 
    | 
    | Available Schemes - basic, session, jwt, api 
    | Available Serializers - Lucid, Database 
    | 
    */ 
    authenticator: 'session', 

    /* 
    |-------------------------------------------------------------------------- 
    | Session Authenticator 
    |-------------------------------------------------------------------------- 
    | 
    | Session authenticator will make use of sessions to maintain the login 
    | state for a given user. 
    | 
    */ 
    session: { 
    serializer: 'Lucid', 
    model: 'App/Model/User', 
    scheme: 'session', 
    uid: 'email', 
    password: 'password' 
    }, 

    /* 
    |-------------------------------------------------------------------------- 
    | Basic Auth Authenticator 
    |-------------------------------------------------------------------------- 
    | 
    | Basic Authentication works on Http Basic auth header. 
    | 
    */ 
    basic: { 
    serializer: 'Lucid', 
    model: 'App/Model/User', 
    scheme: 'basic', 
    uid: 'email', 
    password: 'password' 
    }, 

    /* 
    |-------------------------------------------------------------------------- 
    | JWT Authenticator 
    |-------------------------------------------------------------------------- 
    | 
    | Jwt authentication works with a payload sent with every request under 
    | Http Authorization header. 
    | 
    */ 
    jwt: { 
    serializer: 'Lucid', 
    model: 'App/Model/User', 
    scheme: 'jwt', 
    uid: 'email', 
    password: 'password', 
    secret: Config.get('app.appKey') 
    }, 

    /* 
    |-------------------------------------------------------------------------- 
    | API Authenticator 
    |-------------------------------------------------------------------------- 
    | 
    | Api authenticator authenticates are requests based on Authorization 
    | header. 
    | 
    | Make sure to define relationships on User and Token model as defined 
    | in documentation 
    | 
    */ 
    api: { 
    serializer: 'Lucid', 
    model: 'App/Model/Token', 
    scheme: 'api' 
    } 

} 

설정을

routes.js : 여기

내가 지금까지 한 일이다 /shield.js

'use strict' 

module.exports = { 
    /* 
    |-------------------------------------------------------------------------- 
    | Content Security Policy 
    |-------------------------------------------------------------------------- 
    | 
    | Content security policy filters out the origins not allowed to execute 
    | and load resources like scripts, styles and fonts. There are wide 
    | variety of options to choose from. 
    | @examples 
    | directives: { 
    | defaultSrc: ['self', '@nonce', 'cdnjs.cloudflare.com'] 
    | } 
    */ 
    csp: { 
    directives: { 
    }, 
    reportOnly: false, 
    setAllHeaders: false, 
    disableAndroid: true 
    }, 

    /* 
    |-------------------------------------------------------------------------- 
    | X-XSS-Protection 
    |-------------------------------------------------------------------------- 
    | 
    | X-XSS Protection saves from applications from XSS attacks. It is adopted 
    | by IE and later followed by some other browsers. 
    | 
    */ 
    xss: { 
    enabled: true, 
    enableOnOldIE: false 
    }, 

    /* 
    |-------------------------------------------------------------------------- 
    | Iframe Options 
    |-------------------------------------------------------------------------- 
    | 
    | xframe defines whether or not your website can be embedded inside an 
    | iframe. Choose from one of the following options. 
    | @available options 
    | DENY, SAMEORIGIN, ALLOW-FROM http://example.com 
    */ 
    xframe: 'DENY', 

    /* 
    |-------------------------------------------------------------------------- 
    | No Sniff 
    |-------------------------------------------------------------------------- 
    | 
    | Browsers have a habit of sniffing content-type of a response. Which means 
    | files with .txt extension containing Javascript code will be executed as 
    | Javascript. You can disable this behavior by setting nosniff to false. 
    | 
    */ 
    nosniff: true, 

    /* 
    |-------------------------------------------------------------------------- 
    | No Open 
    |-------------------------------------------------------------------------- 
    | 
    | IE users can execute webpages in the context of your website, which is 
    | a serious security risk. Below options will manage this for you. 
    | 
    */ 
    noopen: true, 

    /* 
    |-------------------------------------------------------------------------- 
    | CSRF Protection 
    |-------------------------------------------------------------------------- 
    | 
    | CSRF Protection adds another layer of security by making sure, actionable 
    | routes does have a valid token to execute an action. 
    | 
    */ 
    csrf: { 
    enable: true, 
    methods: ['POST', 'PUT', 'DELETE'], 
    filterUris: ['/api/v1/login', '/api/v1/register'], 
    compareHostAndOrigin: true 
    } 

} 

이제 로그인 웹 서비스 (우편 배달부 사용)를 누릅니다. 사용자의 유효성을 검사하지만 const token = request.auth.generate(user)에 예외가 발생하고 request.auth.generate is not a function이라고 표시됩니다.

나는 무슨 일이 일어나고 있는지 모른다. 도와주세요.

감사

하고 저장 한 후 나중에 요청을하는 데 사용할 수있는 로그인 서비스를 요청한 응용 프로그램은 (사용 있도록 (사용자가 로그인 API 호출을 호출 할 때)는 JWT 토큰을 생성하고 다시 보낼 필요가
+0

3.2 또는 4.0을 사용하고 있습니까? 새 프로젝트 인 경우 4.0 (ndlr : http://dev.adonisjs.com/)으로 전환하는 것이 좋습니다. –

+0

나는'adonis --version'을했는데 2.1.9를 주었다. adonisjs를 어떻게 업데이트 할 수 있습니까? 필자는 공식 문서 http://adonisjs.com/docs/3.2/installation에 설명 된대로 정확히 동일한 단계를 따라 설치했습니다. 'package.json'의 – Ali

+0

''버전 ":"3.2.1 "' – Ali

답변

1

"Bearer [JWT Token String]"값을 갖는 "Authorization"헤더). 앱에서 다른 요청 (예 : 비즈니스 카테고리 목록 가져 오기) (헤더에 JWT 토큰 포함)을 보내면 API 미들웨어에서 해당 요청의 유효성을 검사합니다. 요청의 유효성이 확인되면 요청을 처리하고 json 형식으로 데이터를 전송합니다.

여기 당신의 헤더는 모습입니다 같은 :

image

그리고 이것은 당신이 실제로 코드에서해야 할 일이다

// ROUTES.JS

// API Routes 
Route.post('/api/v1/register', 'ApiController.register') 
Route.post('/api/v1/login', 'ApiController.login') 

Route.group('api', function() { 

    Route.get('/business_categories', 'ApiController.business_categories') 

}).prefix('/api/v1').middlewares(['api']) 

// API.JS (미들웨어)

'use strict' 

class Api { 

    * handle (request, response, next) { 

    // here goes your middleware logic 
    const authenticator = request.auth.authenticator('jwt') 
    const isLoggedIn = yield authenticator.check() 

    if (!isLoggedIn) { 
     return response.json({ 
     status: 0, 
     response: { 
      message: 'API Authentication Failed.' 
     } 
     }) 
    } 

    // yield next to pass the request to next middleware or controller 
    yield next 

    } 

} 

module.exports = Api 

//은 만료되거나 삭제되지 않는 한 (강제로 사용자 아웃 로그인 할 때, 응용 프로그램에서)

'use strict' 

// Dependencies 
const Env = use('Env') 
const Validator = use('Validator') 
const Config = use('Config') 
const Database = use('Database') 
const Helpers = use('Helpers') 
const RandomString = use('randomstring') 
const Email = use('emailjs') 
const View = use('View') 

// Models 
const User = use('App/Model/User') 
const UserProfile = use('App/Model/UserProfile') 
const DesignCenter = use('App/Model/DesignCenter') 
const Settings = use('App/Model/Setting') 

// Properties 
const FAIL  = 0 
const SUCCESS = 1 
const SITE_URL = "http://"+Env.get('HOST')+":"+Env.get('PORT') 

// Messages 
const MSG_API_AUTH_FAILED    = 'Api Authentication Failed.' 
const MSG_REGISTERED_SUCCESS   = 'Registered Successfully.' 
const MSG_LOGGED_IN_SUCCESS   = 'Logged In Successfully.' 
const MSG_LOGGED_IN_CHECK    = 'You Are Logged In.' 
const MSG_LOGGED_IN_FAIL    = 'Invalid Credentials.' 
const MSG_FORGOT_PASS_EMAIL_SUCCESS = 'Your password reset email has been sent. Please check your inbox to continue.' 

class ApiController { 

    * register (request, response) { 

    let jsonResponse = {} 

    // validate form input 
    const validation = yield Validator.validateAll(request.all(), Config.get('validation.api.register.rules'), Config.get('validation.api.register.messages')) 

    // show error messages upon validation fail 
    if (validation.fails()) { 

     jsonResponse.status = FAIL 
     jsonResponse.response = {} 
     jsonResponse.response.message = validation.messages()[0].message 

    } else { 

     // handle card image 
     let card_image = null 

     if (request.file('card_image')) { 

     const image = request.file('card_image', { 
      allowedExtensions: ['jpg', 'png', 'jpeg'] 
     }) 

     if (image.clientSize() > 0) { 
      const filename = RandomString.generate({length: 30, capitalization: 'lowercase'}) + '.' + image.extension() 
      yield image.move(Helpers.publicPath(Config.get('constants.user_card_img_upload_path')), filename) 

      if (!image.moved()) { 
      jsonResponse.status = FAIL 
      jsonResponse.response = {} 
      jsonResponse.response.message = image.errors() 
      return response.json(jsonResponse) 
      } 

      // set value for DB 
      card_image = filename 
     } 

     } 

     // create user 
     const user = yield User.create({ 
     username: new Date().getTime(), 
     email: request.input('email'), 
     password: request.input('password') 
     }) 

     // create user profile 
     const user_profile = yield UserProfile.create({ 
     user_id: user.id, 
     user_type_id: 3, // designer 
     first_name: request.input('first_name'), 
     last_name: request.input('last_name'), 
     business_name: request.input('business_name'), 
     business_category_id: request.input('business_category'), 
     card_image: card_image, 
     phone: request.input('mobile_no'), 
     is_active: 1 
     }) 

     jsonResponse.status = SUCCESS 
     jsonResponse.response = {} 
     jsonResponse.response.message = MSG_REGISTERED_SUCCESS 
     jsonResponse.response.user = { 
     'id': user.id, 
     'first_name': user_profile.first_name, 
     'last_name': user_profile.last_name, 
     'business_name': user_profile.business_name, 
     'business_category_id': user_profile.business_category_id, 
     'card_image': user_profile.card_image == null ? "" : SITE_URL + "/" + Config.get('constants.user_card_img_upload_path') + "/" + user_profile.card_image, 
     'mobile_no': user_profile.phone 
     } 

    } 

    return response.json(jsonResponse) 

    } 

    * login (request, response) { 

    let jsonResponse = {} 

    const email = request.input('email') 
    const password = request.input('password') 

    // validate form input 
    const validation = yield Validator.validateAll(request.all(), Config.get('validation.api.login.rules'), Config.get('validation.api.login.messages')) 

    if (validation.fails()) { 

     jsonResponse.status = FAIL 
     jsonResponse.response = {} 
     jsonResponse.response.message = validation.messages()[0].message 

    } else { 

     try { 
     const jwt = request.auth.authenticator('jwt') 
     const token = yield jwt.attempt(email, password) 
     const user = yield User.findBy('email', email) 
     const user_profile = yield UserProfile.findBy('user_id', user.id) 

     // check if user type is designer 
     if (user_profile.user_type_id == 3) { 

      jsonResponse.status = SUCCESS 
      jsonResponse.response = {} 
      jsonResponse.response.message = MSG_LOGGED_IN_SUCCESS 

      let card_image = null 
      if (user_profile.card_image) { 
      card_image = SITE_URL + "/" + Config.get('constants.user_card_img_upload_path') + "/" + user_profile.card_image 
      } 

      jsonResponse.response.user = { 
      'id': user.id, 
      'first_name': user_profile.first_name, 
      'last_name': user_profile.last_name, 
      'business_name': user_profile.business_name, 
      'business_category_id': user_profile.business_category_id, 
      'card_image': card_image, 
      'mobile_no': user_profile.phone 
      } 
      jsonResponse.response.token = token 

     } else { 

      jsonResponse.status = FAIL 
      jsonResponse.response = {} 
      jsonResponse.response.message = MSG_LOGGED_IN_FAIL 

     } 
     } catch (e) { 
     jsonResponse.status = FAIL 
     jsonResponse.response = {} 
     jsonResponse.response.message = e.message 
     } 

    } 

    return response.json(jsonResponse) 

    } 

    * business_categories (request, response) { 

    let jsonResponse = {} 

    try { 

     jsonResponse.status = SUCCESS 
     const dbRecords = yield Database.select('id', 'name').from('business_categories') 
     let records = [] 

     dbRecords.forEach(function(row) { 
     records.push({ 
      id: row.id, 
      name: row.name 
     }) 
     }) 

     jsonResponse.response = records 

    } catch (e) { 

     jsonResponse.status = FAIL 
     jsonResponse.response = {} 
     jsonResponse.response.message = e.message 

    } 

    response.json(jsonResponse) 

} 

module.exports = ApiController 

// CONFIG/AUTH.JS가

는 JWT 토큰이 유효하기 때문에 APICONTROLLER.JS. 또한 다음과 같이 만료 기간을 설정할 수 있습니다.

jwt: { 
    serializer: 'Lucid', 
    model: 'App/Model/User', 
    scheme: 'jwt', 
    uid: 'email', 
    password: 'password', 
    secret: Config.get('app.appKey'), 
    options: { 
     // Options to be used while generating token 
     expiresIn: Ms('3m') // 3 months 
    } 
} 

// CONFIG/SHIELD.

csrf: { 
    enable: true, 
    methods: ['POST', 'PUT', 'DELETE'], 
    filterUris: [ 
     '/api/v1/login', 
     '/api/v1/register' 
    ], 
    compareHostAndOrigin: true 
} 
: JS

POST 요청을 보내는 동안 API 서비스의 대부분은 CSRF 토큰을 보낼 수 없습니다 때문에, 당신은 CSRF 점검 할되지 않은 API 경로를 제외 할 수는 다음과 같이이 파일에 여기 토큰

희망 사항 :

+0

신난다, 나는 잠시 그것에 시험해 볼 것이다. – Ali