@account=Account.find_by_username_and_password(@username,@password)
if @account
session[:account]=@account#保存登录用户信息,再根据权限跳转相应页面
redirect_to :controller=>"teacher",:action => "teacher" if @account.power==1
redirect_to :controller=>"student",:action => "student" if @account.power==2
student 登录后在 student.html.erb 中可以正常访问到 session
<%=session[:account]%>
student.html.erb 中有个 ext 的改密码按钮,请求路径为
url:'/student/changepw'
但是我在 def changepw 中却取不到 session 了
session[:account]
为空
这是为什么呢?是 rails 中的 session 和以前的 java 有区别还是我理解错了 session 的本意呢?:)
Ext 改密码,这个表单渲染在 student.html.erb 的一个 div 标签中
var password=new Ext.form.FormPanel({
defaultType:'textfield',
title:'更改密码',
frame:true,
url:'/student/changepw',
items:[{name:'op',fieldLabel:'原密码',allowBlank:false,inputType:"password"},
{name:'np1',fieldLabel:'新密码',allowBlank:false,inputType:"password"},
{name:'np2',fieldLabel:'确认密码',allowBlank:false,inputType:"password"},
{
xtype:'button',
text:'修改密码',
handler : function() {
password.getForm().submit({
success : function(password, action) { Ext.Msg.alert(action.result.msg1, action.result.msg2); },
failure : function() { Ext.Msg.alert('错误', '程序存在异常'); }
});
}
}]
});
url 转发了一下请求 在 changepw 这个方法就读不到 session 了 费解
def changepw
@op=params[:op]#原密码
@np1=params[:np1]#新密码1
@np2=params[:np2]#新密码2
if session[:account]
@test='OK'
else
@test='empty'
end
render :text=>"{success:true,msg1:'"+@test+"',msg2:'"+@test+"'}"
end#函数结尾
Ext 的 alert 一直蹦的是 empty-.- 明明是在一个请求过程中的,为什么我的 session 么有了呢
看不到所有代码和实际环境,估计大家很难帮到你 提供个思路给你: 向 session 中写的这个对象实际上是被序列化以后放到了 cookie 中 建议你安装 http 抓包工具 (比如 http watch 或者 chrome 自带的),抓取 http 包,分析里面的 cookie 头,看看什么情况 cookie 字符串你只需要取出--前面的部分然后反 base64 即可看到明文了
你把整个 student 的 obj 存进 cookie,觉得不是太好,最好是存一个 id 就可以了,避免有 cookie 撑爆的情况。 tail 出 log 来看看有没有报错。
有诚意的话放整段代码,要不然就自己找 bug
在公司带我的两个老师说应该是 Ext 重新发送请求的时候相当于又开了一个浏览器 (因为他们说 ext 的界面都是在 div 的层上的),所以我的 session 没了 但是他们说他们 50% 确定-.-当然那两个老师都是搞 java 的不会 rails 不也就不好问是不是 rails 和 java 的区别了
登录是用 Ext 作的界面
Ext.onReady(function() {
var form = new Ext.form.FormPanel( {
labelAlign : 'right',
title : '用户登录',
labelWidth : 50,
buttonAlign : 'center',
frame : true,
width : 220,
items : [ {
xtype:'textfield',
fieldLabel : '用户',
name : 'text1'
},{
xtype:'textfield',
inputType:"password",
fieldLabel : '密码',
name : 'text2'
}],
buttons : [ {
text : '登录',
handler : function() {
form.getForm().getEl().dom.action='/login/login';
form.getForm().getEl().dom.submit();
}
} ]
});
form.render("form");
});
Login 的 controller
class LoginController < ApplicationController
def index #显示登录页
end
def login
@username=params[:text1]
@password=params[:text2]
@account=Account.find_by_username_and_password(@username,@password)
if @account
session[:account]=@account#保存登录用户信息,再根据权限跳转相应页面
redirect_to :controller=>"teacher",:action => "teacher" if @account.power==1
redirect_to :controller=>"student",:action => "student" if @account.power==2
else
render :action => "error"
end
end
def error#显示错误页面
end
end
Student的controller
class StudentController < ApplicationController
def student#学生的默认界面student.html.erb
end
def changepw
@op=params[:op]#原密码
@np1=params[:np1]#新密码1
@np2=params[:np2]#新密码2
if session[:account]
@test='OK' #我把业务代码都删除专门用这段判断出我的session没有值
else #因为我Ext的对话框一直蹦的是empty
@test='empty'
end
render :text=>"{success:true,msg1:'"+@test+"',msg2:'"+@test+"'}"
end
end
Ext 改密码的表单 渲染在 student.html.erb 页面的 div 中
var password=new Ext.form.FormPanel({
defaultType:'textfield',
title:'更改密码',
frame:true,
url:'/student/changepw',
items:[{name:'op',fieldLabel:'原密码',allowBlank:false,inputType:"password"},
{name:'np1',fieldLabel:'新密码',allowBlank:false,inputType:"password"},
{name:'np2',fieldLabel:'确认密码',allowBlank:false,inputType:"password"},
{
xtype:'button',
text:'修改密码',
handler : function() {
password.getForm().submit({
success : function(password, action) { Ext.Msg.alert(action.result.msg1, action.result.msg2); },
failure : function() { Ext.Msg.alert('错误', '程序存在异常'); }
});
}
}]
});
麻烦前辈再给瞅瞅:) 都是一个 request 下来的 只不过登录后进行改密码,改密码的时候在 Ext 里写的 url 进行重定位,结果到重定位的方法里就得不到 session 了
form 发出去的是 post 请求吧,rails 中的 post 请求默认都是需要 crsf_token 的,如果用 extjs 构造的 form,很可能没有 token 值。而 rails 在 post 请求中找不到 token 的话会重置 session。
@cantin 多谢前辈 问题和您说的一样,是 crsf_token 的问题,在提交一个 ajax 请求的时候,当请求方式为 post 的时候,rails 如果开启了 protect_from_forgery。那么在提交的 post 数据中就必须加入 token 这个字段来通过 rails 的后端验证。 在 rails3.0.4 以前的版本,没有提交 token 字段会报错,但是在以后的版本里面,rails 会自动重置 session 即 session 丢失。 我把 application_controller.rb 中的 protect_from_forgery 去掉就可以得到之前的 session 了 但我知道这也不是个办法:) 继续探索中
class ApplicationController < ActionController::Base
protect_from_forgery # 这里不用动
end
class PostsController < ApplicationController
protect_from_forgery :except => :upload # 在这里加一句
end
之前也遇到这个问题,ajax 上传导致用户登录状态丢失
没有用过 EXTJS 但是 RAILS.JS 里对于:method => :remote
的 LINK 是这样做的
var csrf_token = $('meta[name=csrf-token]').attr('content'),
csrf_param = $('meta[name=csrf-param]').attr('content');
$('a[data-method]:not([data-remote])').live('click', function (e){
var link = $(this),
href = link.attr('href'),
method = link.attr('data-method'),
form = $('<form method="post" action="'+href+'"></form>'),
metadata_input = '<input name="_method" value="'+method+'" type="hidden" />';
if (csrf_param != null && csrf_token != null) {
metadata_input += '<input name="'+csrf_param+'" value="'+csrf_token+'" type="hidden" />';
}
form.hide()
.append(metadata_input)
.appendTo('body');
e.preventDefault();
form.submit();
});
或许你可以在 EXTJS 里模仿一下
应该有两种方法,一是可以在 post 发过去的参数中加上 token 值,在 layouts/application.html.erb 中的 csrf_meta_tag 就是在 head 中加入一个 meta 标签,其中存放了 token 的值,可以使用 js 取得它的值,然后随着 post 请求发过去(可以参考其他 form 提交时发过去的参数),二是在 post 请求的 header 里面设置这个 token,这个方法我没使用过,网上应该是可以找得到的。