我正在创建一个使用JWT令牌进行身份验证的AngularJS应用程序。使用AngularJS拦截器传递令牌,如下所示。
'request': function(config)
{
if (store.get('jwt_token') != null)
{
config.headers['x-access-token'] = store.get('jwt_token');
}
else
{
config.headers['x-access-token'] = '';
}
return config;
}
每当我访问任何 /restricted
页面时,一切正常。问题是,当我通过在地址栏中直接输入网址(或刷新页面)进入 /restricted
页面时,AngularJS会被规避,因此,拦截器不会拦截请求,并且不会传递令牌。
我已经搜索了一段时间,我找到了一些解决方案,例如用一段加载AngularJS的代码进行响应然后从那里进行重定向。但是,我正在寻找一种更简单/更简洁的方法,因为我可能会遗漏一些内容。
我可以通过检查 x-access-token
来检测请求是否来自AngularJS,因为我总是传递它(如果用户未经过身份验证,则为空值)。< / p>
解决方案
亚历克斯的回答指出了确切的问题,谢谢Alex。
我昨天终于明白了。我使用的解决方案是确保所有请求都来自AngularJS,我有一个受限页面列表,如果有任何请求,我调用一个函数来验证和验证服务器端的JWT令牌如果它有效,请继续,否则,请转到登录页面。 关键是要确保所有请求都应该转到index.html以确保AngularJS正在处理路由。
这个链接帮助我解决了这个问题。
http://arthur.gonigberg.com/2013/06/29/angularjs-role-based-auth/
答案 0 :(得分:2)
听起来好像Angular的路由器和服务器端点之间存在混淆。
您可能会在浏览应用程序时触发$ http配置,使用Angular路由器跟踪的URL(工作正常),而import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class HomePage extends Fragment {
public HomePage(){}
String[] listitems;
int[] images = {R.drawable.cadburysilk,R.drawable.cadburys_dairymilk,R.drawable.perk,
R.drawable.kitkat,R.drawable.nestlemunchchocolate,R.drawable.cadbury_bournville_bar,
R.drawable.snickers};
ListView list;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreateView(inflater, container, savedInstanceState);
View rootview = inflater.inflate(R.layout.activity_home_page, container, false);
Resources res = getResources();
listitems=res.getStringArray(R.array.items);
list = (ListView)rootview.findViewById(R.id.itemslist);
AdapterClass adapterClass = new AdapterClass(HomePage.this.getActivity(), listitems, images);
list.setAdapter(adapterClass);
return rootview;
}
}
class AdapterClass extends ArrayAdapter<String>
{
Context context;
int[] images;
String[] names;
public AdapterClass(Context c, String[] items,int imgs[] ) {
// TODO Auto-generated constructor stub
super(c, R.layout.rowlayout, R.id.quantity, items );
this.context = c;
this.images = imgs;
this.names = items;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.rowlayout, parent, false);
ImageView imageView = (ImageView) row.findViewById(R.id.img);
TextView textView = (TextView) row.findViewById(R.id.textView1);
imageView.setImageResource(images[position]);
textView.setText(names[position]);
return row;
}
}
URL是服务器 URL。
因此,当您在Angular应用程序之外(在浏览器中)请求任何/restricted
时,它会将请求直接发送到服务器,而不是通过Angular路由器或应用程序。
基本上,您需要在Angular应用程序中创建/restricted
上下文中的路由,在初始化时,运行$ http配置。您永远不应该直接在地址栏中调用服务器端点,restricted
(index.html
)除外。
我建议使用名为/
的Angular路由,以便当用户点击它时,它将始终使用您拥有的$ http方法,通过专用的Angular路由,调用服务器的{{1}内部端点,通过控制器。
答案 1 :(得分:2)
我在2个月前问了类似的问题。我所理解的是,通常在javascript前端框架之前,如何提供http请求:
但是随着最近向各种javascript前端框架的转变以及RESTful api.s的使用已经开始,请求需要具有授权标头。因此,在许多具有javascript框架的单页网页应用程序中,例如angularjs,
所以当你从角度应用程序发出请求时。您的请求是从角度应用程序截取并被您的拦截器截获的。但是,当您从地址栏输入URL时,浏览器会直接向服务器发送请求,因为在请求的那一点,浏览器尚未加载您的角度Web应用程序。
我建议您将html5mode设置为false并在路线前放置#
。
与localhost/#/restricted
类似,并从路由提供商处进行路由。当您的路由前有#
时,/
的请求将转到服务器,您的应用程序将加载,并从您的应用程序中/restricted
创建一个控制器,将http请求发送到所需的服务器端点。通过这种方式,请求将通过您的应用程序发送,并将被您的拦截器截获。刷新并直接在地址栏中输入地址也可以。
答案 2 :(得分:0)
我认为如果您访问 / restricted 页面,您的Angular应用程序将正常启动,这只是一个登录问题。
如果您没有令牌,则必须重定向到登录页面。您可以将登录显示为模态叠加,然后您无需切换页面。拦截器将监视状态401的响应结果。在这种情况下,拦截器将显示登录。成功登录后,拦截器将使用令牌执行原始请求。
您可以在angular app
中找到一个有效的例子答案 3 :(得分:-2)
只需在Cookie中传递此令牌,而不是在标题中传递。