Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
xyqb-user2
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
head_group
xyqb-user2
Commits
c6910d8c
Commit
c6910d8c
authored
Jan 05, 2017
by
zhouqian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
登录增加系统key
parent
6fc20b5a
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
65 additions
and
40 deletions
+65
-40
AppController.java
...antgroup/xyqb/controller/external/user/AppController.java
+11
-2
Jr58Controller.java
...ntgroup/xyqb/controller/external/user/Jr58Controller.java
+3
-3
UserController.java
...ntgroup/xyqb/controller/internal/user/UserController.java
+25
-13
SessionValue.java
...n/java/cn/quantgroup/xyqb/model/session/SessionValue.java
+1
-0
IAuthApiService.java
...java/cn/quantgroup/xyqb/service/auth/IAuthApiService.java
+3
-3
AuthApiServiceImpl.java
...quantgroup/xyqb/service/auth/impl/AuthApiServiceImpl.java
+8
-7
ISessionService.java
...a/cn/quantgroup/xyqb/service/session/ISessionService.java
+5
-3
SessionServiceImpl.java
...ntgroup/xyqb/service/session/impl/SessionServiceImpl.java
+9
-9
No files found.
src/main/java/cn/quantgroup/xyqb/controller/external/user/AppController.java
View file @
c6910d8c
...
...
@@ -2,6 +2,7 @@ package cn.quantgroup.xyqb.controller.external.user;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.controller.IBaseController
;
import
cn.quantgroup.xyqb.entity.Merchant
;
import
cn.quantgroup.xyqb.entity.User
;
import
cn.quantgroup.xyqb.entity.UserDetail
;
import
cn.quantgroup.xyqb.exception.NullUserException
;
...
...
@@ -10,6 +11,7 @@ import cn.quantgroup.xyqb.model.session.SessionStruct;
import
cn.quantgroup.xyqb.repository.IUserDetailRepository
;
import
cn.quantgroup.xyqb.repository.IUserRepository
;
import
cn.quantgroup.xyqb.service.auth.IIdCardService
;
import
cn.quantgroup.xyqb.service.merchant.IMerchantService
;
import
cn.quantgroup.xyqb.service.session.ISessionService
;
import
cn.quantgroup.xyqb.service.sms.ISmsService
;
import
cn.quantgroup.xyqb.service.user.ILkbUserService
;
...
...
@@ -60,6 +62,8 @@ public class AppController implements IBaseController {
private IUserDetailRepository userDetailRepository;*/
@Autowired
private
IIdCardService
idCardService
;
@Autowired
private
IMerchantService
merchantService
;
private
final
static
Random
random
=
new
Random
();
...
...
@@ -71,11 +75,12 @@ public class AppController implements IBaseController {
public
JsonResult
login
(
String
phoneNo
,
@RequestParam
(
required
=
false
,
defaultValue
=
"0"
)
Long
registerFrom
,
String
idNo
,
String
name
,
HttpServletRequest
request
String
idNo
,
String
name
,
String
key
,
HttpServletRequest
request
)
{
if
(!
ValidationUtil
.
validatePhoneNo
(
phoneNo
))
{
return
JsonResult
.
buildErrorStateResult
(
"该用户名不存在,<br/>请重新输入或注册新账号。"
,
null
);
}
String
requestIp
=
IPUtil
.
getRemoteIP
(
request
);
LOGGER
.
info
(
"第三方用户登录, loginFrom:{}, requestIp:{}"
,
registerFrom
,
requestIp
);
User
user
=
userService
.
findByPhoneInDb
(
phoneNo
);
...
...
@@ -85,10 +90,14 @@ public class AppController implements IBaseController {
if
(
user
==
null
)
{
return
JsonResult
.
buildErrorStateResult
(
"该用户名不存在,<br/>请重新输入或注册新账号。"
,
null
);
}
Merchant
merchant
=
merchantService
.
findMerchantByName
(
key
);
if
(
merchant
==
null
)
{
return
JsonResult
.
buildErrorStateResult
(
"无效的商户"
,
null
);
}
SessionStruct
sessionStruct
=
sessionService
.
createSessionAndPersist
(
user
,
session
->
{
session
.
setAttribute
(
"channelId"
,
"1"
);
session
.
setAttribute
(
"createdFrom"
,
String
.
valueOf
(
registerFrom
));
});
}
,
merchant
);
AuthBean
bean
=
new
AuthBean
();
...
...
src/main/java/cn/quantgroup/xyqb/controller/external/user/Jr58Controller.java
View file @
c6910d8c
...
...
@@ -184,7 +184,7 @@ public class Jr58Controller implements ApplicationEventPublisherAware {
User
userInXyqb
=
xyqbUserService
.
findByUuidWithCache
(
uuid
);
if
(
userInXyqb
!=
null
)
{
String
token
=
authApiService
.
login
(
userInXyqb
.
getPhoneNo
(),
Constants
.
Channel
.
JR58
);
String
token
=
authApiService
.
login
(
userInXyqb
.
getPhoneNo
(),
Constants
.
Channel
.
JR58
,
"xyqb"
);
return
new
Tuple
<>(
String
.
format
(
ENTRY_POINT_URL_TEMPLATE
,
xyqbUrl
,
token
),
userInXyqb
);
}
...
...
@@ -198,12 +198,12 @@ public class Jr58Controller implements ApplicationEventPublisherAware {
// 手机号在新系统中存在,说明之前已经注册过
userInXyqb
=
xyqbUserService
.
findByPhoneWithCache
(
phoneNo
);
if
(
userInXyqb
!=
null
)
{
String
token
=
authApiService
.
login
(
phoneNo
,
Constants
.
Channel
.
JR58
);
String
token
=
authApiService
.
login
(
phoneNo
,
Constants
.
Channel
.
JR58
,
"xyqb"
);
return
new
Tuple
<>(
String
.
format
(
ENTRY_POINT_URL_TEMPLATE
,
xyqbUrl
,
token
),
userInXyqb
);
}
else
{
// 注册过
userInXyqb
=
xyqbUserService
.
registerAndReturn
(
phoneNo
,
"abc1234$"
,
Constants
.
Channel
.
JR58
);
String
token
=
authApiService
.
login
(
phoneNo
,
Constants
.
Channel
.
JR58
);
String
token
=
authApiService
.
login
(
phoneNo
,
Constants
.
Channel
.
JR58
,
"xyqb"
);
return
new
Tuple
<>(
String
.
format
(
ENTRY_POINT_URL_TEMPLATE
,
xyqbUrl
,
token
),
userInXyqb
);
}
}
...
...
src/main/java/cn/quantgroup/xyqb/controller/internal/user/UserController.java
View file @
c6910d8c
...
...
@@ -2,6 +2,7 @@ package cn.quantgroup.xyqb.controller.internal.user;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.controller.IBaseController
;
import
cn.quantgroup.xyqb.entity.Merchant
;
import
cn.quantgroup.xyqb.entity.User
;
import
cn.quantgroup.xyqb.entity.UserDetail
;
import
cn.quantgroup.xyqb.exception.UserNotExistException
;
...
...
@@ -9,6 +10,7 @@ import cn.quantgroup.xyqb.model.AuthBean;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.model.UserModel
;
import
cn.quantgroup.xyqb.model.session.SessionStruct
;
import
cn.quantgroup.xyqb.service.merchant.IMerchantService
;
import
cn.quantgroup.xyqb.service.session.ISessionService
;
import
cn.quantgroup.xyqb.service.sms.ISmsService
;
import
cn.quantgroup.xyqb.service.user.IUserDetailService
;
...
...
@@ -59,6 +61,8 @@ public class UserController implements IBaseController {
@Autowired
private
IUserDetailService
userDetailService
;
@Autowired
private
IMerchantService
merchantService
;
private
static
final
char
[]
PWD_BASE
=
{
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
,
'g'
,
'h'
,
'i'
,
'j'
,
'k'
,
'l'
,
'm'
,
'n'
,
'o'
,
'p'
,
'q'
,
'r'
,
's'
,
't'
,
'u'
,
'v'
,
'w'
,
...
...
@@ -68,11 +72,15 @@ public class UserController implements IBaseController {
public
JsonResult
login
(
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
channelId
,
String
appChannel
,
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
createdFrom
,
@RequestParam
(
required
=
false
,
defaultValue
=
""
)
String
userId
,
HttpServletRequest
request
)
{
@RequestParam
(
required
=
false
,
defaultValue
=
""
)
String
userId
,
String
key
,
HttpServletRequest
request
)
{
Merchant
merchant
=
merchantService
.
findMerchantByName
(
key
);
if
(
merchant
==
null
)
{
return
JsonResult
.
buildErrorStateResult
(
"未知的连接"
,
null
);
}
if
(!
StringUtils
.
isEmpty
(
userId
)
&&
userId
.
length
()
>
10
)
{
return
loginWithUserId
(
channelId
,
appChannel
,
createdFrom
,
userId
);
return
loginWithUserId
(
channelId
,
appChannel
,
createdFrom
,
userId
,
merchant
);
}
else
{
return
loginWithHttpBasic
(
channelId
,
appChannel
,
createdFrom
,
request
);
return
loginWithHttpBasic
(
channelId
,
appChannel
,
createdFrom
,
merchant
,
request
);
}
}
...
...
@@ -85,21 +93,25 @@ public class UserController implements IBaseController {
@RequestMapping
(
"/login/fast"
)
public
JsonResult
loginFast
(
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
channelId
,
String
appChannel
,
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
createdFrom
,
HttpServletRequest
request
){
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
createdFrom
,
String
key
,
HttpServletRequest
request
){
Map
<
String
,
JsonResult
>
validMap
=
getHeaderParam
(
request
);
if
(
null
!=
validMap
.
get
(
"fail"
)){
return
validMap
.
get
(
"fail"
);
}
Merchant
merchant
=
merchantService
.
findMerchantByName
(
key
);
if
(
merchant
==
null
)
{
return
JsonResult
.
buildErrorStateResult
(
"未知的连接"
,
null
);
}
JsonResult
successResult
=
validMap
.
get
(
"success"
);
String
phoneNo
=
successResult
.
getData
().
toString
();
User
user
=
userService
.
findByPhoneWithCache
(
phoneNo
);
if
(
user
==
null
){
if
(
user
==
null
)
{
user
=
registerFastWhenLogin
(
phoneNo
,
channelId
,
createdFrom
,
appChannel
);
if
(
user
==
null
)
{
throw
new
UserNotExistException
(
"用户未找到"
);
}
}
return
createSession
(
channelId
,
createdFrom
,
appChannel
,
user
);
return
createSession
(
channelId
,
createdFrom
,
appChannel
,
user
,
merchant
);
// return createSession(channelId, createdFrom, appChannel, user);
}
...
...
@@ -361,19 +373,19 @@ public class UserController implements IBaseController {
}
private
JsonResult
loginWithHttpBasic
(
Long
channelId
,
String
appChannel
,
Long
createdFrom
,
HttpServletRequest
request
)
{
private
JsonResult
loginWithHttpBasic
(
Long
channelId
,
String
appChannel
,
Long
createdFrom
,
Merchant
merchant
,
HttpServletRequest
request
)
{
User
user
=
verificateUserNameAndPassword
(
request
);
if
(
user
==
null
)
{
return
JsonResult
.
buildErrorStateResult
(
"用户名或密码不正确"
,
null
);
}
else
{
return
createSession
(
channelId
,
createdFrom
,
appChannel
,
user
);
return
createSession
(
channelId
,
createdFrom
,
appChannel
,
user
,
merchant
);
}
}
private
JsonResult
createSession
(
Long
channelId
,
Long
createdFrom
,
String
appChannel
,
User
user
)
{
private
JsonResult
createSession
(
Long
channelId
,
Long
createdFrom
,
String
appChannel
,
User
user
,
Merchant
merchant
)
{
AuthBean
authBean
=
new
AuthBean
();
//找到用户
String
sessionId
=
sessionService
.
findSessionIdByUserId
(
user
.
getId
()
);
String
sessionId
=
sessionService
.
findSessionIdByUserId
AndMerchant
(
user
.
getId
(),
merchant
);
if
(
StringUtils
.
isNotEmpty
(
sessionId
))
{
SessionStruct
sessionStruct
=
sessionService
.
findSessionBySessionId
(
sessionId
);
sessionStruct
.
setAttribute
(
"channelId"
,
String
.
valueOf
(
channelId
));
...
...
@@ -389,7 +401,7 @@ public class UserController implements IBaseController {
session
.
setAttribute
(
"channelId"
,
String
.
valueOf
(
channelId
));
session
.
setAttribute
(
"createdFrom"
,
String
.
valueOf
(
createdFrom
));
session
.
setAttribute
(
"appChannel"
,
String
.
valueOf
(
appChannel
));
});
}
,
merchant
);
authBean
.
setPhoneNo
(
user
.
getPhoneNo
());
authBean
.
setToken
(
sessionStruct
.
getSid
());
LOGGER
.
info
(
"用户登录成功, loginFrom:{}, phoneNo:{},appChannel:{}"
,
createdFrom
,
user
.
getPhoneNo
(),
appChannel
);
...
...
@@ -430,12 +442,12 @@ public class UserController implements IBaseController {
return
StringUtils
.
defaultString
(
targetPassword
,
""
).
equals
(
PasswordUtil
.
MD5
(
paramPass
.
toLowerCase
()
+
pwdSalt
));
}
private
JsonResult
loginWithUserId
(
Long
channelId
,
String
appChannel
,
Long
createdFrom
,
String
userId
)
{
private
JsonResult
loginWithUserId
(
Long
channelId
,
String
appChannel
,
Long
createdFrom
,
String
userId
,
Merchant
merchant
)
{
//查询用户,存在则保存用户session信息,userId为uuid
User
user
=
userService
.
findByUuidInDb
(
userId
);
//用户信息存在,更新session中的最后访问时间,重新写入缓存.
if
(
null
!=
user
)
{
return
createSession
(
channelId
,
createdFrom
,
appChannel
,
user
);
return
createSession
(
channelId
,
createdFrom
,
appChannel
,
user
,
merchant
);
}
else
{
return
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
);
}
...
...
src/main/java/cn/quantgroup/xyqb/model/session/SessionValue.java
View file @
c6910d8c
...
...
@@ -22,5 +22,6 @@ public class SessionValue{
private
Timestamp
createdAt
;
@JSONField
(
serializeUsing
=
Timestamp2LongConverter
.
class
)
private
Timestamp
lastAccessTime
;
private
String
merchantName
;
}
src/main/java/cn/quantgroup/xyqb/service/auth/IAuthApiService.java
View file @
c6910d8c
...
...
@@ -6,9 +6,9 @@ package cn.quantgroup.xyqb.service.auth;
*/
public
interface
IAuthApiService
{
String
login
(
String
phone
,
Long
loginFrom
);
String
login
(
String
phone
,
Long
loginFrom
,
String
key
);
String
login
(
String
phone
,
Long
loginFrom
,
Long
channelId
);
String
login
(
String
phone
,
Long
loginFrom
,
Long
channelId
,
String
key
);
String
login
(
String
phone
,
Long
loginFrom
,
Long
channelId
,
Long
createdFrom
);
String
login
(
String
phone
,
Long
loginFrom
,
Long
channelId
,
Long
createdFrom
,
String
key
);
}
src/main/java/cn/quantgroup/xyqb/service/auth/impl/AuthApiServiceImpl.java
View file @
c6910d8c
...
...
@@ -30,18 +30,18 @@ public class AuthApiServiceImpl implements IAuthApiService {
private
String
xyqbAuthUrl
;
@Override
public
String
login
(
String
phone
,
Long
loginFrom
)
{
return
this
.
getToken
(
phone
,
loginFrom
,
1L
,
loginFrom
);
public
String
login
(
String
phone
,
Long
loginFrom
,
String
key
)
{
return
this
.
getToken
(
phone
,
loginFrom
,
1L
,
loginFrom
,
key
);
}
@Override
public
String
login
(
String
phone
,
Long
loginFrom
,
Long
channelId
)
{
return
this
.
getToken
(
phone
,
loginFrom
,
channelId
,
loginFrom
);
public
String
login
(
String
phone
,
Long
loginFrom
,
Long
channelId
,
String
key
)
{
return
this
.
getToken
(
phone
,
loginFrom
,
channelId
,
loginFrom
,
key
);
}
@Override
public
String
login
(
String
phone
,
Long
loginFrom
,
Long
channelId
,
Long
createdFrom
)
{
return
this
.
getToken
(
phone
,
loginFrom
,
channelId
,
createdFrom
);
public
String
login
(
String
phone
,
Long
loginFrom
,
Long
channelId
,
Long
createdFrom
,
String
key
)
{
return
this
.
getToken
(
phone
,
loginFrom
,
channelId
,
createdFrom
,
key
);
}
/**
...
...
@@ -50,12 +50,13 @@ public class AuthApiServiceImpl implements IAuthApiService {
* @param phone
* @return
*/
private
String
getToken
(
String
phone
,
Long
loginFrom
,
Long
channelId
,
Long
createdFrom
)
{
private
String
getToken
(
String
phone
,
Long
loginFrom
,
Long
channelId
,
Long
createdFrom
,
String
key
)
{
Map
<
String
,
String
>
parameters
=
ImmutableMap
.<
String
,
String
>
builder
()
.
put
(
"phoneNo"
,
phone
)
.
put
(
"registerFrom"
,
loginFrom
+
""
)
.
put
(
"channelId"
,
channelId
+
""
)
.
put
(
"createdFrom"
,
createdFrom
+
""
)
.
put
(
"key"
,
key
)
.
build
();
String
response
=
httpService
.
post
(
xyqbAuthUrl
+
"/app/login"
,
parameters
);
...
...
src/main/java/cn/quantgroup/xyqb/service/session/ISessionService.java
View file @
c6910d8c
package
cn
.
quantgroup
.
xyqb
.
service
.
session
;
import
cn.quantgroup.xyqb.entity.Merchant
;
import
cn.quantgroup.xyqb.entity.User
;
import
cn.quantgroup.xyqb.function.OneArgFunction
;
import
cn.quantgroup.xyqb.model.session.SessionStruct
;
...
...
@@ -9,11 +10,12 @@ import cn.quantgroup.xyqb.model.session.SessionValue;
* Created by 11 on 2016/12/28.
*/
public
interface
ISessionService
{
SessionStruct
createSessionAndPersistInCache
(
User
user
);
SessionStruct
createSessionAndPersistInCache
(
User
user
,
Merchant
merchant
);
SessionStruct
createSessionAndPersist
(
User
user
,
OneArgFunction
<
SessionStruct
>
function
);
String
findSessionIdByUserId
(
Long
userId
);
SessionStruct
createSessionAndPersist
(
User
user
,
OneArgFunction
<
SessionStruct
>
beforPersist
,
Merchant
merchant
);
String
findSessionIdByUserIdAndMerchant
(
Long
userId
,
Merchant
merchant
);
String
findSessionValueBySessionId
(
String
sessionId
);
SessionStruct
newSession
(
User
user
);
void
persistSession
(
String
token
,
SessionValue
sessionValue
);
...
...
src/main/java/cn/quantgroup/xyqb/service/session/impl/SessionServiceImpl.java
View file @
c6910d8c
package
cn
.
quantgroup
.
xyqb
.
service
.
session
.
impl
;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.entity.Merchant
;
import
cn.quantgroup.xyqb.entity.User
;
import
cn.quantgroup.xyqb.function.OneArgFunction
;
import
cn.quantgroup.xyqb.model.session.SessionStruct
;
import
cn.quantgroup.xyqb.model.session.SessionValue
;
import
cn.quantgroup.xyqb.service.session.ISessionService
;
import
cn.quantgroup.xyqb.session.XyqbSessionContextHolder
;
import
com.alibaba.fastjson.JSON
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -32,15 +32,15 @@ public class SessionServiceImpl implements ISessionService{
private
RedisTemplate
<
String
,
String
>
stringRedisTemplate
;
@Override
public
SessionStruct
createSessionAndPersistInCache
(
User
user
)
{
return
createSessionAndPersist
(
user
,
null
);
public
SessionStruct
createSessionAndPersistInCache
(
User
user
,
Merchant
merchant
)
{
return
createSessionAndPersist
(
user
,
null
,
merchant
);
}
@Override
public
SessionStruct
createSessionAndPersist
(
User
user
,
OneArgFunction
<
SessionStruct
>
beforPersist
)
{
public
SessionStruct
createSessionAndPersist
(
User
user
,
OneArgFunction
<
SessionStruct
>
beforPersist
,
Merchant
merchant
)
{
SessionStruct
sessionStruct
;
//获取sessionid
String
sessionId
=
findSessionIdByUserId
(
user
.
getId
()
);
String
sessionId
=
findSessionIdByUserId
AndMerchant
(
user
.
getId
(),
merchant
);
if
(
StringUtils
.
length
(
sessionId
)
==
36
){
sessionStruct
=
new
SessionStruct
();
String
sessionValue
=
findSessionValueBySessionId
(
sessionId
);
...
...
@@ -63,8 +63,8 @@ public class SessionServiceImpl implements ISessionService{
}
@Override
public
String
findSessionIdByUserId
(
Long
userId
)
{
return
stringRedisTemplate
.
opsForValue
().
get
(
Constants
.
Session
.
USER_SESSION_ID_CACHE
+
userId
.
toString
());
public
String
findSessionIdByUserId
AndMerchant
(
Long
userId
,
Merchant
merchant
)
{
return
stringRedisTemplate
.
opsForValue
().
get
(
Constants
.
Session
.
USER_SESSION_ID_CACHE
+
":"
+
merchant
.
getName
()
+
":"
+
userId
.
toString
());
}
@Override
...
...
@@ -89,13 +89,13 @@ public class SessionServiceImpl implements ISessionService{
}
@Override
public
void
persistSession
(
String
token
,
SessionValue
sessionValue
){
public
void
persistSession
(
String
token
,
SessionValue
sessionValue
)
{
Timestamp
current
=
new
Timestamp
(
System
.
currentTimeMillis
());
sessionValue
.
setLastAccessTime
(
current
);
String
json
=
JSON
.
toJSONString
(
sessionValue
);
stringRedisTemplate
.
opsForValue
().
set
(
Constants
.
Session
.
USER_SESSION_CACHE
+
token
,
json
,
Constants
.
Session
.
ONE_DAY
,
TimeUnit
.
SECONDS
);
stringRedisTemplate
.
opsForValue
().
set
(
Constants
.
Session
.
USER_SESSION_ID_CACHE
+
stringRedisTemplate
.
opsForValue
().
set
(
Constants
.
Session
.
USER_SESSION_ID_CACHE
+
":"
+
sessionValue
.
getMerchantName
()
+
":"
+
sessionValue
.
getUser
().
getId
().
toString
(),
token
,
Constants
.
Session
.
ONE_DAY
,
TimeUnit
.
SECONDS
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment