JWT 构建Rails API 授权登录
参考下面的连接
使用Rails构建JSON-API
https://chorder.net/2018/07/31/使用Rails构建JSON-API/
安装jwt组件
Gemfile里添加
# jwt
gem 'jwt'
执行命令:
bundle install
创建base_controller.rb控制器
这个控制器的代码就会位于app/controllers/api/v1/base_controller.rb,我们需要在其中完善一些权限有关的配置。
由于Rails默认的安全属性,以及我们如果之前自定义了一些控制器中的过滤方法,我们需要在该控制器中跳过它,例如我们首先禁用rails自带的CSRF 保护和CSRF token的输出,以及去除掉返回包中的set-cookies头,由于我的应用还使用了devise作为用户认证的模块,所以还要在此禁用掉authenticate_user方法。
完整的代码如下
新建一个控制器
rails g controller api/v1/base --no-assets
class Api::V1::BaseController < ApplicationController
# disable the CSRF token
# protect_from_forgery with: :null_session
# disable cookies (no set-cookies header in response)
# before_action :destroy_session
before_action :check_login
# disable the CSRF token
skip_before_action :verify_authenticity_token
# skip devise user authentication
# skip_before_action :authenticate_user!
# skip_before_action :authenticate_admin!
# def destroy_session
# request.session_options[:skip] = true
# end
@current_user
def check_login
puts "request.path222 #{request.path}"
unless ["/api/v1/login"].include?(request.path)
@current_user = current_user1()
if @current_user.blank?
# render json: {msg: "登录失败", result: false}, status: :forbidden
render json: { statusCode: 4001, messages: "token验证失败,请重新登陆.", data: [] }
end
end
end
def current_user1
if request.headers['Authorization']&.start_with?("Bearer")
jwt_token = request.headers['Authorization'].split&.last
# puts "jwt_token11:#{jwt_token}"
jwt_info = Token::decoded_jwt_infos(jwt_token)
# puts "jwt_info11:#{jwt_info}"
user = User.find_by(id: jwt_info["user_id"])
# puts "jwt_info222:#{jwt_info}"
if Time.parse(jwt_info["exp_at"]) > Time.now && user.present?
user
else
nil
end
end
rescue JWT::ExpiredSignature, JWT::VerificationError
nil
end
end
创建好base控制器以后,我们需要在这个控制器的基础上派生出一些新的控制器,这里我们新建一个login_controller.rb控制器
rails g controller api/v1/login`` --no-assets
此时除了会生成控制器代码以外,还会在app/views/api/v1目录下创建login目录,作为模板存放的目录。
login控制器的代码位于app/controllers/api/v1/login_controller.rb,内容如下
class Api::V1::LoginController < Api::V1::BaseController
def index
# Token.decoded_jwt_infos()
puts "logins index"
end
def create
puts "params[password]:#{params[:password]}"
user = User.find_by(username: params[:username])
unless user.present?
# flash.now[:notice] = "用户名不存在"
# render :index and return
render json: { statusCode: 4002, messages: "用户名不存在", data: [] }
return
end
unless user.valid_password?(params["password"])
render json: { statusCode: 4003, messages: "用户名或密码错误",data:[]}
return
end
if user.category.blank? || user.category != "super_admin"
render json: { statusCode: 4004, messages: "用户没有权限",data:[]}
return
end
# render json: payload(@member)
data = {
id: user.id,
username: user.username,
category: user.category,
token: Token.encode(user) }
render json: { statusCode: 200, messages: "SUCCESS", data: data }
end
def check_token
puts "#{Time.now} @check_token22->:#{@current_user.to_json}"
user = @current_user
puts "#{Time.now} user333:#{user.to_json}"
# Token.decoded_jwt_infos()
# user = current_user
# @user = User.find(params[:id])
data = {
id: user.id,
username: user.username,
category: user.category }
render json: { statusCode: 200, messages: "ok", data: data }
end
end
配置路由
接下来我们对路由config/routes.rb进行配置
namespace :api do
namespace :v1 do
resources :login, only: [:create] do
collection do
post :check_token
end
end
end
end
启动Rails程序
rails s
用户登陆-api接口
访问接口
访问http://127.0.0.1:3000/api/v1/login,即可看到接口输出的JSON数据。
curl -X POST 'http://10.10.11.133:8080/api/v1/login' \
--header 'Content-Type: application/json' \
--data '{
"username": "admin",
"password":"123456"
}'
响应示例
成功响应示例
{
"statusCode": 200,
"messages": "SUCCESS",
"data": {
"id": 1, //用户id
"username": "admin", //用户登陆名
"category": "super_admin", //角色类型:super_admin:超级管理员
"token": "eyJhbGciOiJIUzI1NiJ9.eyJleHBfYXQiOiIyMDIyLTAxLTE3IDExOjU5OjU4ICswODAwIiwidXNlcl9pZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9.Fens2VDYy8Br6FyEtcCyMa4caUWrfGcGr2gLtu77dCM" //登陆token
} //返回数据
}
验证用户token信息-api接口(*)
curl --location --request POST 'http://10.10.11.133:8080/api/v1/login/check_token' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJleHBfYXQiOiIyMDIyLTAxLTE3IDExOjU5OjU4ICswODAwIiwidXNlcl9pZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9.Fens2VDYy8Br6FyEtcCyMa4caUWrfGcGr2gLtu77dCM'
响应示例
成功响应示例
{
"statusCode": 200,
"messages": "SUCCESS",
"data": {
"id": 1, //用户id
"username": "admin", //用户登陆名
"category": "super_admin" //角色类型:super_admin:超级管理员
} //返回数据
}
[Haima的博客]
http://www.cnblogs.com/haima/