Play framework and ionic for mobile 我需要 Security without cookies 但 token
Play framework and ionic for mobile I need Security without cookies but token
我在使用在 Ionic 中创建的移动应用程序和在 play 框架中编码的后端 API 时遇到问题,我的问题只是我需要一种方法来处理调用需要保护的 API 的安全问题,意味着用户必须登录才能执行操作,例如来宾可以查看组但只有在登录后才能加入。
我的问题是移动设备不支持 cookie,我有存储在 cookie 中的代码检查会话,它适用于网站,但不适用于移动设备,对吗?
目前我正在尝试发送一个令牌,该令牌在后端生成并随登录响应返回并存储在 Ionic 的 localStorage 中,但我的问题是我无法发送令牌以通过请求进行验证。
前端:
我有以下 http 拦截器:
angular
.module('app.core')
.factory('sessionInjector', sessionInjector);
/** @ngInject */
function sessionInjector($q, sessionService, $rootScope) {
return {
request: function (config) {
$rootScope.$broadcast('loading:show');
if (!sessionService.isAnonymous())
config.headers['x-session-token'] = sessionService.getToken();
}
return config;
}
}
后端:
控制器:
@Security.Authenticated(Secure.class)
public Result joinOrganization() {
// Do some business
}
Secure.java :
@Override
public String getUsername(Http.Context ctx) {
// Is this correct way? I get null here
String str = ctx.request().getHeader("x-session-token");
String userId = ctx.session().get("usedId");
if (userId == null) {
return null;
}
User user = Play.application().injector().instanceOf(UserService.class).findUserById(Integer.parseInt(userId));
if (user != null && user.isActive) {
return user.id;
} else {
return null;
}
}
@Override
public Result onUnauthorized(Http.Context ctx) {
return unauthorized(results);
}
注意:数据库中存储的令牌:
实体:
@Entity
@Table(name = "AUTHTOKEN")
public class AuthToken extends BaseModel {
@OneToOne(targetEntity = User.class, cascade = CascadeType.REFRESH, optional = false)
public User user;
@Column(nullable = false)
public String token;
@Column
public long expiration;
public AuthToken() {
}
}
对于 cookie 工作,但需要删除 cookie 并使用令牌,或者将它们一起用于网站 cookie,移动令牌。
在 cookie 方面,移动设备与其他设备没有什么不同。如果使用 AJAX 或跨域请求会有限制,特别是对于 Apple 的东西,但它们也适用于非移动设备。如果您的 cookie 在 PC/Mac 上工作,它们在移动设备上也应该能正常工作。它比其他任何东西都更重要...
我找到了解决方案,但它很复杂,因为从那开始有很多问题 ngResource does not apply request interceptor 这是一个很久以前就打开的问题。
第二个问题是如何使用 ngResource
发送令牌,只需添加 headers
,这里的另一个问题是动态获取令牌,这个 "dynamically" 意味着因为 localStorage
刷新时内存丢失,所以你需要取回它,这可以通过服务和获取令牌的函数调用来完成,如下所示:
$resource('/user/:userId/card/:cardId', {userId:123, cardId:'@id'}, {
charge: {method:'POST', params:{charge:true}, headers = {
'x-session-token': function () {
return sessionService.getToken()
}}
});
会话服务内部:
// this to recreate the cache in memory once the user refresh, it will keep the data if exisit but will point to it again in memory
if (CacheFactory.get('profileCache') == undefined) {
//if there is no cache already then create new one and assign it to profileCache
CacheFactory.createCache('profileCache');
}
function getCurrentSession() {
var profileCache = CacheFactory.get('profileCache');
if (profileCache !== undefined && profileCache.get('Token') !== undefined) {
return profileCache.get('Token');
}
return null;
}
function getToken() {
var currentSession = getCurrentSession();
if (currentSession != null && currentSession != '') {
return currentSession.token;
}
return null;
}
然后这个方法将在Secure.java
中起作用
protected User getUser(Http.Context ctx) {
String token = ctx.request().getHeader("x-session-token");
if (token != null) {
return securityService.validateToken(token);
}
return null;
}
我在使用在 Ionic 中创建的移动应用程序和在 play 框架中编码的后端 API 时遇到问题,我的问题只是我需要一种方法来处理调用需要保护的 API 的安全问题,意味着用户必须登录才能执行操作,例如来宾可以查看组但只有在登录后才能加入。
我的问题是移动设备不支持 cookie,我有存储在 cookie 中的代码检查会话,它适用于网站,但不适用于移动设备,对吗?
目前我正在尝试发送一个令牌,该令牌在后端生成并随登录响应返回并存储在 Ionic 的 localStorage 中,但我的问题是我无法发送令牌以通过请求进行验证。
前端: 我有以下 http 拦截器:
angular
.module('app.core')
.factory('sessionInjector', sessionInjector);
/** @ngInject */
function sessionInjector($q, sessionService, $rootScope) {
return {
request: function (config) {
$rootScope.$broadcast('loading:show');
if (!sessionService.isAnonymous())
config.headers['x-session-token'] = sessionService.getToken();
}
return config;
}
}
后端: 控制器:
@Security.Authenticated(Secure.class)
public Result joinOrganization() {
// Do some business
}
Secure.java :
@Override
public String getUsername(Http.Context ctx) {
// Is this correct way? I get null here
String str = ctx.request().getHeader("x-session-token");
String userId = ctx.session().get("usedId");
if (userId == null) {
return null;
}
User user = Play.application().injector().instanceOf(UserService.class).findUserById(Integer.parseInt(userId));
if (user != null && user.isActive) {
return user.id;
} else {
return null;
}
}
@Override
public Result onUnauthorized(Http.Context ctx) {
return unauthorized(results);
}
注意:数据库中存储的令牌:
实体:
@Entity
@Table(name = "AUTHTOKEN")
public class AuthToken extends BaseModel {
@OneToOne(targetEntity = User.class, cascade = CascadeType.REFRESH, optional = false)
public User user;
@Column(nullable = false)
public String token;
@Column
public long expiration;
public AuthToken() {
}
}
对于 cookie 工作,但需要删除 cookie 并使用令牌,或者将它们一起用于网站 cookie,移动令牌。
在 cookie 方面,移动设备与其他设备没有什么不同。如果使用 AJAX 或跨域请求会有限制,特别是对于 Apple 的东西,但它们也适用于非移动设备。如果您的 cookie 在 PC/Mac 上工作,它们在移动设备上也应该能正常工作。它比其他任何东西都更重要...
我找到了解决方案,但它很复杂,因为从那开始有很多问题 ngResource does not apply request interceptor 这是一个很久以前就打开的问题。
第二个问题是如何使用 ngResource
发送令牌,只需添加 headers
,这里的另一个问题是动态获取令牌,这个 "dynamically" 意味着因为 localStorage
刷新时内存丢失,所以你需要取回它,这可以通过服务和获取令牌的函数调用来完成,如下所示:
$resource('/user/:userId/card/:cardId', {userId:123, cardId:'@id'}, {
charge: {method:'POST', params:{charge:true}, headers = {
'x-session-token': function () {
return sessionService.getToken()
}}
});
会话服务内部:
// this to recreate the cache in memory once the user refresh, it will keep the data if exisit but will point to it again in memory
if (CacheFactory.get('profileCache') == undefined) {
//if there is no cache already then create new one and assign it to profileCache
CacheFactory.createCache('profileCache');
}
function getCurrentSession() {
var profileCache = CacheFactory.get('profileCache');
if (profileCache !== undefined && profileCache.get('Token') !== undefined) {
return profileCache.get('Token');
}
return null;
}
function getToken() {
var currentSession = getCurrentSession();
if (currentSession != null && currentSession != '') {
return currentSession.token;
}
return null;
}
然后这个方法将在Secure.java
中起作用protected User getUser(Http.Context ctx) {
String token = ctx.request().getHeader("x-session-token");
if (token != null) {
return securityService.validateToken(token);
}
return null;
}