手机端API认证
diff --git a/config/application-devel-pg.properties b/config/application-devel-pg.properties
index 5ea16f5..61b2df9 100644
--- a/config/application-devel-pg.properties
+++ b/config/application-devel-pg.properties
@@ -24,4 +24,8 @@
security.request.sign=false
##################################################
## quartz task scheduler
-shopbalance.updater.cron=-
\ No newline at end of file
+<<<<<<< HEAD
+shopbalance.updater.cron=-
+=======
+shopbalance.updater.cron = -
+>>>>>>> 手机端API认证
diff --git a/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java b/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java
index 16e429a..7255657 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java
@@ -1,16 +1,12 @@
package com.supwisdom.dlpay.framework.filter;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.supwisdom.dlpay.api.bean.JsonResult;
import com.supwisdom.dlpay.exception.ValidateCodeException;
+import com.supwisdom.dlpay.framework.security.MyAuthenticationFailureHandler;
import com.supwisdom.dlpay.framework.security.validate.ImageCodeUtil;
import com.supwisdom.dlpay.framework.security.validate.VerifyCode;
import com.supwisdom.dlpay.framework.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.security.web.authentication.AuthenticationFailureHandler;
-import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
@@ -22,65 +18,69 @@
@Component("validateCodeFilter")
-public class ValidateCodeFilter extends OncePerRequestFilter{
+public class ValidateCodeFilter extends OncePerRequestFilter {
- /**
- * 校验失败处理器
- */
- @Autowired
- private AuthenticationFailureHandler myAuthenticationFailureHandler;
-
- /**
- * 校验成功处理器
- */
- @Autowired
- private AuthenticationSuccessHandler myAuthenticationSuccessHandler;
- @Autowired
- private ObjectMapper objectMapper;
+ /**
+ * 校验失败处理器
+ */
+ @Autowired
+ private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
- @Override
- protected void doFilterInternal(HttpServletRequest request,
- HttpServletResponse response, FilterChain filterChain)
- throws ServletException, IOException {
- if (StringUtil.equals("/login/form", request.getRequestURI())
- && StringUtil.equalsIgnoreCase(request.getMethod(), "post")) {
- try {
- validate(request);
- } catch (ValidateCodeException e) {
- //response.setTransStatus(HttpStatus.OK.value());
- //response.setContentType("application/json;charset=UTF-8");
- //response.getWriter().write(objectMapper.writeValueAsString(JsonResult.error(400, e.getMessage())));
- //response.sendError(HttpStatus.UNAUTHORIZED.value(),e.getMessage());
- myAuthenticationFailureHandler.onAuthenticationFailure(request, response, e);
- return;
- }
- }
- filterChain.doFilter(request, response);
- }
+ @Override
+ protected void doFilterInternal(HttpServletRequest request,
+ HttpServletResponse response, FilterChain filterChain)
+ throws ServletException, IOException {
+ String context = request.getContextPath();
+ if (context == null || "" == context.trim()) {
+ context = "/";
+ }
+ if (request.getRequestURI().isEmpty()) {
+ filterChain.doFilter(request, response);
+ return;
+ }
+ String url = request.getRequestURI();
+ if (!"/".equals(context)) {
+ url = url.replace(context, "");
+ }
+ if (StringUtil.equals("/login/form", url)
+ && StringUtil.equalsIgnoreCase(request.getMethod(), "post")) {
+ try {
+ validate(request);
+ } catch (ValidateCodeException e) {
+ //response.setStatus(HttpStatus.OK.value());
+ //response.setContentType("application/json;charset=UTF-8");
+ //response.getWriter().write(objectMapper.writeValueAsString(JsonResult.error(400, e.getMessage())));
+ //response.sendError(HttpStatus.UNAUTHORIZED.value(),e.getMessage());
+ myAuthenticationFailureHandler.onAuthenticationFailure(request, response, e);
+ return;
+ }
+ }
+ filterChain.doFilter(request, response);
+ }
- private void validate(HttpServletRequest request) throws ValidateCodeException {
- VerifyCode imageCode = (VerifyCode) request.getSession().getAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);
- String inputCode;
- try {
- inputCode = request.getParameter("imageCode");
- } catch (Exception e) {
- throw new ValidateCodeException("获取验证码的值失败");
- }
- if (StringUtil.isEmpty(inputCode)) {
- throw new ValidateCodeException("验证码不能为空");
- }
- if (null == imageCode) {
- throw new ValidateCodeException("验证码不存在");
- }
- if (imageCode.isExpired()) {
- request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);
- throw new ValidateCodeException("验证码已过期");
- }
- if (!StringUtil.equalsIgnoreCase(imageCode.getText(), inputCode)) {
- throw new ValidateCodeException("验证码不匹配");
- }
- request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);
- }
+ private void validate(HttpServletRequest request) throws ValidateCodeException {
+ VerifyCode imageCode = (VerifyCode) request.getSession().getAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);
+ String inputCode;
+ try {
+ inputCode = request.getParameter("imageCode");
+ } catch (Exception e) {
+ throw new ValidateCodeException("获取验证码的值失败");
+ }
+ if (StringUtil.isEmpty(inputCode)) {
+ throw new ValidateCodeException("验证码不能为空");
+ }
+ if (null == imageCode) {
+ throw new ValidateCodeException("验证码不存在");
+ }
+ if (imageCode.isExpired()) {
+ request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);
+ throw new ValidateCodeException("验证码已过期");
+ }
+ if (!StringUtil.equalsIgnoreCase(imageCode.getText(), inputCode)) {
+ throw new ValidateCodeException("验证码不匹配");
+ }
+ request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);
+ }
}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/redisrepo/ApiJwtRepository.java b/src/main/java/com/supwisdom/dlpay/framework/redisrepo/ApiJwtRepository.java
index 38a3fbe..3371b31 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/redisrepo/ApiJwtRepository.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/redisrepo/ApiJwtRepository.java
@@ -2,6 +2,7 @@
import com.supwisdom.dlpay.framework.domain.JwtRedis;
import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
public interface ApiJwtRepository extends CrudRepository<JwtRedis, String> {
}
diff --git a/src/main/kotlin/com/supwisdom/dlpay/mobile/AuthLoginHandler.kt b/src/main/kotlin/com/supwisdom/dlpay/mobile/AuthLoginHandler.kt
new file mode 100644
index 0000000..e1b5869
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/mobile/AuthLoginHandler.kt
@@ -0,0 +1,113 @@
+package com.supwisdom.dlpay.mobile
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.supwisdom.dlpay.api.bean.JsonResult
+import com.supwisdom.dlpay.exception.ValidateCodeException
+import com.supwisdom.dlpay.framework.core.JwtConfig
+import com.supwisdom.dlpay.framework.core.JwtTokenUtil
+import com.supwisdom.dlpay.framework.domain.JwtRedis
+import com.supwisdom.dlpay.framework.redisrepo.ApiClientRepository
+import com.supwisdom.dlpay.framework.redisrepo.ApiJwtRepository
+import com.supwisdom.dlpay.framework.util.DateUtil
+import com.supwisdom.dlpay.framework.util.TradeDict
+import com.supwisdom.dlpay.mobile.dao.MobileUserDao
+import com.supwisdom.dlpay.mobile.domain.TBMobileUser
+import com.supwisdom.dlpay.mobile.exception.UserLoginFailException
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.HttpStatus
+import org.springframework.security.authentication.BadCredentialsException
+import org.springframework.security.authentication.LockedException
+import org.springframework.security.core.Authentication
+import org.springframework.security.core.AuthenticationException
+import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler
+import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler
+import org.springframework.stereotype.Component
+import java.io.IOException
+import javax.servlet.ServletException
+import javax.servlet.http.HttpServletRequest
+import javax.servlet.http.HttpServletResponse
+
+@Component("authLoginSuccessHandler")
+class AuthLoginSuccessHandler : SimpleUrlAuthenticationSuccessHandler() {
+ @Autowired
+ lateinit var mobileUserDao: MobileUserDao
+ @Autowired
+ lateinit var objectMapper: ObjectMapper
+ @Autowired
+ lateinit var jwtConfig: JwtConfig
+ @Autowired
+ lateinit var apiJwtRepository: ApiJwtRepository
+
+ override fun onAuthenticationSuccess(request: HttpServletRequest, response: HttpServletResponse, authentication: Authentication) {
+ logger.error(request?.getParameter("platform"))
+ var temp = authentication!!.principal as TBMobileUser
+ var user = mobileUserDao.findByPhone(temp.phone)
+ if(user!=null) {
+ //TODO 从数据取jwtConfig.expiration
+ val token = JwtTokenUtil(jwtConfig).generateToken(
+ mapOf("uid" to user.uid, "issuer" to "payapi",
+ "audience" to temp.phone,
+ "authorities" to temp.authorities))
+ var jwt = JwtRedis().apply {
+ jti = token.jti
+ uid = temp.phone
+ status = TradeDict.JWT_STATUS_NORMAL
+ expiration = token.expiration.valueInMillis
+ }.apply {
+ //删除之前的token
+ if(!user.jti.isNullOrEmpty()){
+ apiJwtRepository.deleteById(user.jti!!)
+ }
+ apiJwtRepository.save(this)
+ }
+ if (user.loginpwderror != null && user.loginpwderror!! > 0) {
+ user.loginpwderror = 0
+ user.loginpwderrortime = null
+ }
+ user.lastlogin = DateUtil.getNow()
+ user.jti = jwt.jti
+ mobileUserDao.save(user)
+ response.status = HttpStatus.OK.value()
+ response.contentType = "application/json;charset=UTF-8"
+ response.writer.write(objectMapper.writeValueAsString(JsonResult.ok().put("token", token.jwtToken)))
+ }else{
+ throw UserLoginFailException("登录错误")
+ }
+ }
+}
+
+
+@Component("authLoginFailHandler")
+class AuthLoginFailHandler : SimpleUrlAuthenticationFailureHandler() {
+ @Autowired
+ lateinit var mobileUserDao: MobileUserDao
+
+ @Autowired
+ lateinit var objectMapper: ObjectMapper
+
+ @Throws(IOException::class, ServletException::class)
+ override fun onAuthenticationFailure(request: HttpServletRequest,
+ response: HttpServletResponse, exception: AuthenticationException) {
+ logger.error("登录失败:" + exception.message + "|" + exception.javaClass)
+ var errmsg = ""
+ if (exception is BadCredentialsException) {
+ errmsg = "手机号或密码错误"
+ } else if (exception is LockedException) {
+ errmsg = "账户被锁定"
+ } else {
+ errmsg = exception.message!!
+ }
+ var temp = request.getParameter("username")
+ mobileUserDao.findByPhone(temp)?.let {
+ if (it.loginpwderror == null || it.loginpwderror == 0) {
+ it.loginpwderror = 0
+ it.loginpwderrortime = System.currentTimeMillis()
+ }
+ it.loginpwderror += 1
+ mobileUserDao.save(it)
+ }
+ response.status = HttpStatus.OK.value()
+ response.contentType = "application/json;charset=UTF-8"
+ response.writer.write(objectMapper.writeValueAsString(JsonResult.error(errmsg)))
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt b/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
new file mode 100644
index 0000000..a39db67
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
@@ -0,0 +1,38 @@
+package com.supwisdom.dlpay.mobile
+
+import com.supwisdom.dlpay.api.bean.JsonResult
+import com.supwisdom.dlpay.mobile.service.MobileUserService
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.security.core.context.SecurityContextHolder
+import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import javax.servlet.http.HttpServletRequest
+import javax.servlet.http.HttpServletResponse
+import org.springframework.web.bind.annotation.RequestMethod
+import java.security.Principal
+
+
+@RestController
+@RequestMapping("/mobileapi")
+class MobileApiController {
+ @Autowired
+ lateinit var userService: MobileUserService
+ @RequestMapping("/logout")
+ fun logout(request: HttpServletRequest, response: HttpServletResponse): JsonResult {
+ SecurityContextHolder.getContext().authentication?.also {
+ SecurityContextLogoutHandler().logout(request, response, it)
+ }
+ return JsonResult.ok("退出成功")
+ }
+}
+
+@RestController
+@RequestMapping("/mobileapi/v1")
+class ApiV1 {
+ @RequestMapping("/infor")
+ fun getUserInfor(): JsonResult {
+ val p = SecurityContextHolder.getContext().authentication
+ return JsonResult.ok("OK")
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/supwisdom/dlpay/mobile/dao/MobileUserDao.kt b/src/main/kotlin/com/supwisdom/dlpay/mobile/dao/MobileUserDao.kt
new file mode 100644
index 0000000..5261586
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/mobile/dao/MobileUserDao.kt
@@ -0,0 +1,10 @@
+package com.supwisdom.dlpay.mobile.dao
+
+import com.supwisdom.dlpay.mobile.domain.TBMobileUser
+import org.springframework.data.jpa.repository.JpaRepository
+import org.springframework.stereotype.Repository
+
+@Repository
+interface MobileUserDao : JpaRepository<TBMobileUser, String> {
+ fun findByPhone(phone: String): TBMobileUser?
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/supwisdom/dlpay/mobile/domain/TBMobileUser.kt b/src/main/kotlin/com/supwisdom/dlpay/mobile/domain/TBMobileUser.kt
new file mode 100644
index 0000000..da95e4f
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/mobile/domain/TBMobileUser.kt
@@ -0,0 +1,136 @@
+package com.supwisdom.dlpay.mobile.domain
+
+import com.supwisdom.dlpay.framework.util.TradeDict
+import org.springframework.security.core.GrantedAuthority
+import org.springframework.security.core.userdetails.UserDetails
+import javax.persistence.*
+
+@Entity
+@Table(name = "TB_MOBILE_USER")
+class TBMobileUser : UserDetails {
+ override fun getAuthorities(): Collection<GrantedAuthority>? {
+ return this.auths
+ }
+
+ override fun isEnabled(): Boolean {
+ return TradeDict.STATUS_CLOSED != this.status
+ }
+
+ override fun getUsername(): String {
+ return this.phone
+ }
+
+ override fun isCredentialsNonExpired(): Boolean {
+ return true
+ }
+
+ override fun getPassword(): String {
+ return this.loginpwd
+ }
+
+ override fun isAccountNonExpired(): Boolean {
+ return true
+ }
+
+ override fun isAccountNonLocked(): Boolean {
+ return TradeDict.STATUS_LOCKED != this.status
+ }
+ @Transient
+ var auths: Collection<GrantedAuthority>? = null
+
+
+ @Id
+ @Column(name = "uid", nullable = false, length = 32)
+ var uid: String = ""
+ /**
+ * 手机号
+ * */
+ @Column(name = "phone", length = 15)
+ var phone: String = ""
+
+ /**
+ * 设备uuid
+ * */
+ @Column(name = "devuid", length = 64)
+ var devuid: String? = null
+
+ /**
+ * 注册时间
+ * */
+ @Column(name = "registerdate", length = 16)
+ var registerdate: String? = null
+
+ /**
+ * 关联tb_person
+ * */
+ @Column(name = "userid", length = 32)
+ var userid: String? = null
+
+ /**
+ * 注册手机类型
+ * */
+ @Column(name = "registerplatform", length = 20)
+ var registerplatform: String? = null
+
+ /**
+ * 最后登录时间
+ * */
+ @Column(name = "lastlogin", length = 16)
+ var lastlogin: String? = null
+
+ /**
+ * 最后登录手机类型
+ * */
+ @Column(name = "lastloginplatform", length = 20)
+ var lastloginplatform: String? = null
+
+ /**
+ * 状态
+ * */
+ @Column(name = "status", length = 16)
+ var status: String? = null
+
+ /**
+ * 登录密码
+ * */
+ @Column(name = "loginpwd", length = 64)
+ var loginpwd: String = ""
+
+ /**
+ * 支付密码
+ * */
+ @Column(name = "paypwd", length = 64)
+ var paypwd: String? = null
+
+ /**
+ * 登录密码错误次数
+ * */
+ @Column(name = "loginpwderror", length = 4)
+ var loginpwderror: Int = 0
+
+ /**
+ * 登录密码错误时间
+ * */
+ @Column(name = "loginpwderrortime", length = 16)
+ var loginpwderrortime: Long? = 0
+
+ /**
+ * 支付密码错误次数
+ * */
+ @Column(name = "paypwderror", length = 4)
+ var paypwderror: Int = 0
+
+ /**
+ * 支付密码错误时间
+ * */
+ @Column(name = "paypwderrortime", length = 16)
+ var paypwderrortime: Long? = 0
+
+
+ /**
+ * jti
+ * */
+ @Column(name = "jti", length = 64)
+ var jti: String? = null
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/supwisdom/dlpay/mobile/exception/UserLoginFailException.kt b/src/main/kotlin/com/supwisdom/dlpay/mobile/exception/UserLoginFailException.kt
new file mode 100644
index 0000000..67d6243
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/mobile/exception/UserLoginFailException.kt
@@ -0,0 +1,7 @@
+package com.supwisdom.dlpay.mobile.exception
+
+import org.springframework.security.core.AuthenticationException
+
+class UserLoginFailException(msg: String) : AuthenticationException(msg) {
+ private val serialVersionUID = 1170189980006964105L
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/supwisdom/dlpay/mobile/service/MobileApiService.kt b/src/main/kotlin/com/supwisdom/dlpay/mobile/service/MobileApiService.kt
new file mode 100644
index 0000000..c01e430
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/mobile/service/MobileApiService.kt
@@ -0,0 +1,9 @@
+package com.supwisdom.dlpay.mobile.service
+
+import com.supwisdom.dlpay.mobile.domain.TBMobileUser
+
+interface MobileApiService {
+ fun saveUser(user: TBMobileUser): TBMobileUser
+
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/supwisdom/dlpay/mobile/service/MobileUserService.kt b/src/main/kotlin/com/supwisdom/dlpay/mobile/service/MobileUserService.kt
new file mode 100644
index 0000000..6d10c46
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/mobile/service/MobileUserService.kt
@@ -0,0 +1,5 @@
+package com.supwisdom.dlpay.mobile.service
+
+import org.springframework.security.core.userdetails.UserDetailsService
+
+interface MobileUserService : UserDetailsService
\ No newline at end of file
diff --git a/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileApiServiceImpl.kt b/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileApiServiceImpl.kt
new file mode 100644
index 0000000..fec5155
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileApiServiceImpl.kt
@@ -0,0 +1,19 @@
+package com.supwisdom.dlpay.mobile.service.impl
+
+import com.supwisdom.dlpay.framework.util.DateUtil
+import com.supwisdom.dlpay.mobile.dao.MobileUserDao
+import com.supwisdom.dlpay.mobile.domain.TBMobileUser
+import com.supwisdom.dlpay.mobile.service.MobileApiService
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Service
+
+@Service
+class MobileApiServiceImpl : MobileApiService {
+ @Autowired
+ lateinit var mobileUserDao: MobileUserDao
+
+ override fun saveUser(user: TBMobileUser): TBMobileUser {
+ user.lastlogin = DateUtil.getNow()
+ return mobileUserDao.save(user)
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileUserServiceImpl.kt b/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileUserServiceImpl.kt
new file mode 100644
index 0000000..9f16334
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileUserServiceImpl.kt
@@ -0,0 +1,37 @@
+package com.supwisdom.dlpay.mobile.service.impl
+
+import com.supwisdom.dlpay.mobile.dao.MobileUserDao
+import com.supwisdom.dlpay.mobile.domain.TBMobileUser
+import com.supwisdom.dlpay.mobile.exception.UserLoginFailException
+import com.supwisdom.dlpay.mobile.service.MobileUserService
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.security.core.GrantedAuthority
+import org.springframework.security.core.authority.AuthorityUtils
+import org.springframework.security.core.userdetails.UserDetails
+import org.springframework.security.core.userdetails.UsernameNotFoundException
+import org.springframework.stereotype.Service
+
+@Service
+class MobileUserServiceImpl : MobileUserService {
+ @Autowired
+ lateinit var mobileUserDao: MobileUserDao
+
+ override fun loadUserByUsername(username: String?): UserDetails {
+ var temp = mobileUserDao.findByPhone(username!!)
+ if(temp!=null) {
+ if (temp.loginpwderror != null && temp.loginpwderror!! >= 3 && (System.currentTimeMillis() - temp.loginpwderrortime!!) < 1000 * 60 * 30) {
+ throw UserLoginFailException("密码错误次数过多,请稍后再试")
+ } else if (temp.loginpwderror != null && temp.loginpwderror!! >= 3 && (System.currentTimeMillis() - temp.loginpwderrortime!!) > 1000 * 60 * 30) {
+ //更新时间
+ temp.loginpwderror = 0
+ temp.loginpwderrortime = null
+ mobileUserDao.save(temp)
+ }
+ var authorities: Collection<GrantedAuthority> = AuthorityUtils.createAuthorityList("ROLE_USER")
+ temp.auths = authorities
+ }else{
+ throw UsernameNotFoundException("用户不存在")
+ }
+ return temp
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/supwisdom/dlpay/security.kt b/src/main/kotlin/com/supwisdom/dlpay/security.kt
index 514b80c..0914da6 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/security.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/security.kt
@@ -1,13 +1,18 @@
package com.supwisdom.dlpay
+import com.supwisdom.dlpay.api.bean.JsonResult
import com.supwisdom.dlpay.framework.core.JwtConfig
import com.supwisdom.dlpay.framework.core.JwtTokenUtil
import com.supwisdom.dlpay.framework.core.PasswordBCryptConfig
import com.supwisdom.dlpay.framework.redisrepo.ApiJwtRepository
+import com.supwisdom.dlpay.framework.security.MyAuthenticationFailureHandler
import com.supwisdom.dlpay.framework.security.MyPermissionEvaluator
import com.supwisdom.dlpay.framework.security.ValidateCodeSecurityConfig
import com.supwisdom.dlpay.framework.service.OperatorDetailService
import com.supwisdom.dlpay.framework.util.TradeDict
+import com.supwisdom.dlpay.mobile.AuthLoginFailHandler
+import com.supwisdom.dlpay.mobile.AuthLoginSuccessHandler
+import com.supwisdom.dlpay.mobile.service.MobileUserService
import com.supwisdom.dlpay.system.common.DictPool
import org.jose4j.jwt.consumer.InvalidJwtException
import org.jose4j.lang.JoseException
@@ -84,7 +89,7 @@
url = url.replace(context,"")
}
logger.info(url)
- if(!url.startsWith("/api/")){
+ if(!url.startsWith("/api/")&&!url.startsWith("/mobileapi/")){
filterChain.doFilter(request, response)
return
}
@@ -101,6 +106,11 @@
return
}
val claims = getUtil().verifyToken(jwt)
+ if(url.equals("/mobileapi/logout")){
+ SecurityContextHolder.clearContext()
+ apiJwtRepository.deleteById(claims["jti"].toString())
+ throw JoseException("JWT has not been register")
+ }
apiJwtRepository.findById(claims["jti"].toString()).let {
if (!it.isPresent) {
throw JoseException("JWT has not been register")
@@ -119,14 +129,15 @@
if (e.hasExpired()) {
// jwt 过期后返回 401
apiJwtRepository.deleteById(e.jwtContext.jwtClaims.jwtId)
- response.sendError(HttpStatus.UNAUTHORIZED.value(), e.message)
- } else {
- response.sendError(HttpStatus.BAD_REQUEST.value(), e.message)
}
+ response.setStatus(HttpStatus.UNAUTHORIZED.value(), e.message)
+ return
} catch (e: JoseException) {
SecurityContextHolder.clearContext()
// jwt 失效后返回 401
- response.sendError(HttpStatus.UNAUTHORIZED.value(), e.message)
+ response.setStatus(HttpStatus.UNAUTHORIZED.value(), e.message)
+ response.contentType = "application/json;charset=UTF-8"
+ return
}
}
filterChain.doFilter(request, response)
@@ -171,6 +182,60 @@
return super.authenticationManagerBean()
}
}
+ @Configuration
+ @Order(2)
+ class MobileApiSecurityConfigurationAdapter : WebSecurityConfigurerAdapter() {
+ @Autowired
+ lateinit var failureHandler: AuthLoginFailHandler
+ @Autowired
+ lateinit var successHandler: AuthLoginSuccessHandler
+ @Autowired
+ lateinit var passwordBCryptConfig: PasswordBCryptConfig
+
+ @Autowired
+ lateinit var userDetailsService: MobileUserService
+
+ @Autowired
+ lateinit var apiFilter: ApiJwtAuthenticationFilter
+
+ override fun configure(auth: AuthenticationManagerBuilder) {
+ auth.authenticationProvider(userProvider())
+ }
+ @Bean
+ fun userProvider(): DaoAuthenticationProvider {
+ return DaoAuthenticationProvider().apply {
+ setUserDetailsService(userDetailsService)
+ setPasswordEncoder(userPasswordEncoder())
+ }
+ }
+
+ @Bean
+ fun userPasswordEncoder(): BCryptPasswordEncoder {
+ return if (passwordBCryptConfig.seed.isBlank()) {
+ BCryptPasswordEncoder()
+ } else {
+ BCryptPasswordEncoder(passwordBCryptConfig.length,
+ SecureRandom(passwordBCryptConfig.seed.toByteArray()))
+ }
+ }
+
+ override fun configure(http: HttpSecurity) {
+ http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
+ .antMatcher("/mobileapi/**")
+ .addFilterAfter(apiFilter,
+ UsernamePasswordAuthenticationFilter::class.java)
+ .authorizeRequests().anyRequest().authenticated()
+ .and()
+ .formLogin()
+ .loginProcessingUrl("/mobileapi/login")
+ .failureHandler(failureHandler)
+ .successHandler(successHandler)
+ .and().csrf().disable()
+ .sessionManagement().maximumSessions(1)
+ .expiredUrl("/mobileapi/sessionexpired")
+ }
+ }
@Configuration
class MvcWebSecurityConfigurationAdapter : WebSecurityConfigurerAdapter() {
@@ -179,7 +244,7 @@
@Autowired
lateinit var validateCodeSecurityConfig: ValidateCodeSecurityConfig
@Autowired
- lateinit var authenticationFailureHandler: AuthenticationFailureHandler
+ lateinit var authenticationFailureHandler: MyAuthenticationFailureHandler
@Autowired
lateinit var passwordBCryptConfig: PasswordBCryptConfig
@@ -220,7 +285,7 @@
http.apply(validateCodeSecurityConfig)
.and()
.authorizeRequests()
- .antMatchers("/login", "/login/form").permitAll()
+ .antMatchers("/login", "/login/form","/mobileapi/**").permitAll()
.antMatchers("/static/**").permitAll()
.antMatchers("/code/image").permitAll()
.antMatchers("/**").hasAnyRole("USER", "ADMIN")