增加手机验证码登录
This commit is contained in:
parent
4c79271601
commit
594a732d14
@ -87,6 +87,7 @@ public class SystemUserRouteController extends DefaultBaseController {
|
||||
public ModelAndView login(HttpServletRequest request) {
|
||||
ModelAndView mv = new ModelAndView();
|
||||
Map<String, String> pageParams = oAuthService.getPageParams(request);
|
||||
pageParams.put("loginPhoneAction", "oauth/phone");
|
||||
mv.addObject(IUserCenterConst.PAGE_PARAMS, pageParams);
|
||||
mv.addObject(IUserCenterConst.CUSTOM_LOGIN_FORM, loginFormService.getActive());
|
||||
mv.addObject("HomeServerUrl", ProjectConfigUtil.getText("HomeServerUrl"));
|
||||
|
@ -0,0 +1,52 @@
|
||||
package cn.com.tenlion.operator.login.phone;
|
||||
|
||||
import cn.com.tenlion.operator.login.phone.auth.LoginPhoneAuthFilter;
|
||||
import cn.com.tenlion.operator.login.phone.auth.LoginPhoneAuthProvider;
|
||||
import ink.wgink.interfaces.config.ICustomUserSecurityConfig;
|
||||
import ink.wgink.interfaces.expand.login.ILoginHandlerService;
|
||||
import ink.wgink.login.base.handler.LoginFailureHandler;
|
||||
import ink.wgink.login.base.service.user.UserLoginService;
|
||||
import ink.wgink.module.sms.service.sms.ISmsService;
|
||||
import ink.wgink.properties.BaseProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
@Component
|
||||
public class LoginPhoneConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> implements ICustomUserSecurityConfig {
|
||||
|
||||
@Autowired
|
||||
private BaseProperties baseProperties;
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
@Autowired
|
||||
private UserLoginService userLoginService;
|
||||
@Autowired(required = false)
|
||||
private ILoginHandlerService loginHandler;
|
||||
@Autowired
|
||||
private HttpSession httpSession;
|
||||
@Autowired
|
||||
private ISmsService smsService;
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) throws Exception {
|
||||
super.configure(http);
|
||||
LoginPhoneAuthFilter loginPhoneAuthFilter = new LoginPhoneAuthFilter(smsService);
|
||||
loginPhoneAuthFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
|
||||
loginPhoneAuthFilter.setAuthenticationFailureHandler(new LoginFailureHandler(baseProperties.getLoginFailure()));
|
||||
|
||||
LoginPhoneAuthProvider loginPhoneAuthProvider = new LoginPhoneAuthProvider(userDetailsService,
|
||||
userLoginService,
|
||||
loginHandler,
|
||||
httpSession
|
||||
);
|
||||
http.authenticationProvider(loginPhoneAuthProvider).addFilterBefore(loginPhoneAuthFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package cn.com.tenlion.operator.login.phone.auth;
|
||||
|
||||
import ink.wgink.login.base.exceptions.UserAuthenticationException;
|
||||
import ink.wgink.module.sms.service.sms.ISmsService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LoginPhoneAuthFilter extends AbstractAuthenticationProcessingFilter {
|
||||
|
||||
private ISmsService smsService;
|
||||
|
||||
public LoginPhoneAuthFilter(ISmsService smsService) {
|
||||
super(new AntPathRequestMatcher("/oauth/phone", "POST"));
|
||||
this.smsService = smsService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
|
||||
String phone = request.getParameter("username").trim();
|
||||
String code = request.getParameter("code").trim();
|
||||
if (StringUtils.isBlank(phone)) {
|
||||
throw new UserAuthenticationException("手机号不能为空");
|
||||
}
|
||||
if (StringUtils.isBlank(code)) {
|
||||
throw new UserAuthenticationException("验证码不能为空");
|
||||
}
|
||||
// String verifyCode = smsService.getVerifyCode(phone);
|
||||
// if (StringUtils.isBlank(verifyCode)) {
|
||||
// throw new UserAuthenticationException("验证码错误");
|
||||
// }
|
||||
// if (!StringUtils.equals(code, verifyCode)) {
|
||||
// throw new UserAuthenticationException("验证码不匹配");
|
||||
// }
|
||||
LoginPhoneAuthToken loginPhoneAuthToken = new LoginPhoneAuthToken(phone, null);
|
||||
loginPhoneAuthToken.setDetails(authenticationDetailsSource.buildDetails(request));
|
||||
return this.getAuthenticationManager().authenticate(loginPhoneAuthToken);
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package cn.com.tenlion.operator.login.phone.auth;
|
||||
|
||||
import ink.wgink.interfaces.expand.login.ILoginHandlerService;
|
||||
import ink.wgink.login.base.consts.IUserCenterConst;
|
||||
import ink.wgink.login.base.enums.LoginTypeEnum;
|
||||
import ink.wgink.login.base.exceptions.UserAuthenticationException;
|
||||
import ink.wgink.login.base.service.user.UserLoginService;
|
||||
import ink.wgink.pojo.bos.LoginUser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
public class LoginPhoneAuthProvider implements AuthenticationProvider {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LoginPhoneAuthProvider.class);
|
||||
private UserDetailsService userDetailsService;
|
||||
private UserLoginService userLoginService;
|
||||
private ILoginHandlerService loginHandler;
|
||||
private HttpSession httpSession;
|
||||
|
||||
public LoginPhoneAuthProvider(UserDetailsService userDetailsService, UserLoginService userLoginService, ILoginHandlerService loginHandler, HttpSession httpSession) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
this.userLoginService = userLoginService;
|
||||
this.loginHandler = loginHandler;
|
||||
this.httpSession = httpSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
LoginPhoneAuthToken loginPhoneAuthToken = (LoginPhoneAuthToken) authentication;
|
||||
String username = (String) loginPhoneAuthToken.getPrincipal();
|
||||
httpSession.setAttribute(IUserCenterConst.LOGIN_USERNAME, username);
|
||||
LoginUser loginUser = (LoginUser) userDetailsService.loadUserByUsername(username);
|
||||
userLoginService.setLoginUserInfo(loginUser);
|
||||
if (loginUser.getAuthorities().isEmpty()) {
|
||||
throw new UserAuthenticationException(loginUser.getUsername() + "用户无任何角色");
|
||||
}
|
||||
// 登录逻辑处理
|
||||
loginHandler(loginUser);
|
||||
// 清空session中的错误信息
|
||||
httpSession.removeAttribute(IUserCenterConst.ERROR_MESSAGE);
|
||||
httpSession.removeAttribute(IUserCenterConst.LOGIN_USERNAME);
|
||||
// 更新登录信息
|
||||
userLoginService.updateUserLoginInfo(loginUser.getUserId(), loginUser.getUserName(), LoginTypeEnum.USERNAME_AND_PASSWORD.getValue());
|
||||
LoginPhoneAuthToken loginPhoneAuthTokenResult = new LoginPhoneAuthToken(loginUser, null, loginUser.getAuthorities());
|
||||
loginPhoneAuthTokenResult.setDetails(loginPhoneAuthToken.getDetails());
|
||||
return loginPhoneAuthTokenResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> aClass) {
|
||||
return LoginPhoneAuthToken.class.isAssignableFrom(aClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录处理
|
||||
*
|
||||
* @param loginUser
|
||||
*/
|
||||
private void loginHandler(LoginUser loginUser) {
|
||||
if (loginHandler != null) {
|
||||
try {
|
||||
loginHandler.handle(loginUser);
|
||||
} catch (Exception e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
throw new UserAuthenticationException("登录异常");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package cn.com.tenlion.operator.login.phone.auth;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class LoginPhoneAuthToken extends AbstractAuthenticationToken {
|
||||
|
||||
private final Object principal;
|
||||
private Object credentials;
|
||||
|
||||
public LoginPhoneAuthToken(Object principal, Object credentials) {
|
||||
super(null);
|
||||
this.principal = principal;
|
||||
this.credentials = credentials;
|
||||
setAuthenticated(false);
|
||||
}
|
||||
|
||||
public LoginPhoneAuthToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(authorities);
|
||||
this.principal = principal;
|
||||
this.credentials = credentials;
|
||||
setAuthenticated(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return credentials;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return principal;
|
||||
}
|
||||
|
||||
}
|
@ -288,7 +288,6 @@
|
||||
}
|
||||
#loginBox .denglu .yzmtx1 {
|
||||
position: relative;
|
||||
display: none;
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
@ -306,7 +305,6 @@
|
||||
border: none;
|
||||
}
|
||||
#loginBox .denglu .yzmbox1 {
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
@ -404,11 +402,11 @@
|
||||
<div id="loginBox" class="layadmin-user-login-main">
|
||||
<div class="btnlist">
|
||||
<div>
|
||||
<button id="zhanghaomima">账号密码</button>
|
||||
<button id="zhanghaomima" @click="loginTypeChange('zhanghaomima')">账号密码</button>
|
||||
<span class="span1"></span>
|
||||
</div>
|
||||
<div>
|
||||
<button id="yzmlongin">验证码登录</button>
|
||||
<button id="yzmlongin" @click="loginTypeChange('yanzhengma')">验证码登录</button>
|
||||
<span class="span2"></span>
|
||||
</div>
|
||||
|
||||
@ -425,22 +423,22 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="loginFormBox" class="layadmin-user-login-box layadmin-user-login-body layui-form">
|
||||
<form id="loginForm" :action="pageParams.loginFormAction" method="post" @submit.prevent="submitForm" class="denglu">
|
||||
<form id="loginForm" :action="activeAction" method="post" @submit.prevent="submitForm" class="denglu">
|
||||
<input type="hidden" name="referToken" v-model="formData.referToken"/>
|
||||
<div class="layui-form-item">
|
||||
<label class="layadmin-user-login-icon layui-icon layui-icon-username" for="username"></label>
|
||||
<input type="text" v-model="formData.username" id="username" name="username" lay-verify="username" placeholder="用户名" class="layui-input">
|
||||
</div>
|
||||
<div class="layui-form-item mima" id="passwordBox" >
|
||||
<div class="layui-form-item mima" id="passwordBox" v-if="loginType === 'zhanghaomima'">
|
||||
<label class="layadmin-user-login-icon layui-icon layui-icon-password" for="password"></label>
|
||||
<input type="password" v-model="formData.password" id="password" name="password" lay-verify="password" placeholder="密码" class="layui-input">
|
||||
</div>
|
||||
<div class="yzmbox1" @click="getLoginVerificationCode">
|
||||
<div class="yzmbox1" @click="getLoginVerificationCode" v-if="loginType === 'yanzhengma'">
|
||||
<span id="yzm11">点击获取验证码</span>
|
||||
</div>
|
||||
<div class="yzmtx1">
|
||||
<label class="layadmin-user-login-icon layui-icon layui-icon-password" for="password"></label>
|
||||
<input type="text" placeholder="请输入验证码" id="inputyzm11">
|
||||
<div class="yzmtx1" v-if="loginType === 'yanzhengma'">
|
||||
<label class="layadmin-user-login-icon layui-icon layui-icon-password" for="inputyzm11"></label>
|
||||
<input type="text" v-model="formData.code" name="code" placeholder="请输入验证码" lay-verify="code" id="inputyzm11">
|
||||
</div>
|
||||
<div class="layui-form-item" id="verificationCodeBox" v-if="pageParams.verificationCode == 'true'" >
|
||||
<!-- 验证码 -->
|
||||
@ -525,6 +523,8 @@
|
||||
el: '#app',
|
||||
data: {
|
||||
pageParams: pageParams,
|
||||
loginType: 'zhanghaomima',
|
||||
activeAction: pageParams.loginFormAction,
|
||||
formData: {
|
||||
referToken: pageParams.referToken,
|
||||
verificationCode: '',
|
||||
@ -680,7 +680,15 @@
|
||||
$('#loginForm').submit();
|
||||
})
|
||||
},
|
||||
|
||||
loginTypeChange: function(type) {
|
||||
if(type === 'zhanghaomima') {
|
||||
this.activeAction = this.pageParams.loginFormAction;
|
||||
}
|
||||
if(type === 'yanzhengma') {
|
||||
this.activeAction = this.pageParams.loginPhoneAction;
|
||||
}
|
||||
this.loginType = type;
|
||||
}
|
||||
},
|
||||
mounted: function() {
|
||||
var self = this;
|
||||
@ -703,6 +711,11 @@
|
||||
return '密码不能为空';
|
||||
}
|
||||
},
|
||||
code: function(value, item) {
|
||||
if(!value) {
|
||||
return '验证码不能为空';
|
||||
}
|
||||
},
|
||||
verificationCode: function(value, item) {
|
||||
if(!value) {
|
||||
return '验证码不能为空';
|
||||
@ -713,6 +726,7 @@
|
||||
})
|
||||
|
||||
// 切换账号密码登录和验证码登录
|
||||
let loginForm = document.querySelector("#loginForm");
|
||||
let mima = document.querySelector(".mima")
|
||||
let yzmbox1 = document.querySelector('.yzmbox1')
|
||||
let yzmtx1 = document.querySelector(".yzmtx1")
|
||||
@ -731,10 +745,7 @@
|
||||
span2.style.display = 'none'
|
||||
yzmlongin.style.fontWeight = 400
|
||||
yzmlongin.style.borderBottom = '0'
|
||||
mima.style.display = 'block'
|
||||
bixuan.style.display = 'block'
|
||||
yzmtx1.style.display = 'none'
|
||||
yzmbox1.style.display = 'none'
|
||||
})
|
||||
// 验证码登录
|
||||
document.querySelector('#yzmlongin').addEventListener('click', function () {
|
||||
@ -744,10 +755,7 @@
|
||||
span2.style.display = 'block'
|
||||
zhanghaomima.style.fontWeight = 400
|
||||
zhanghaomima.style.borderBottom = '0'
|
||||
mima.style.display = 'none'
|
||||
bixuan.style.display = 'none'
|
||||
yzmtx1.style.display = 'block'
|
||||
yzmbox1.style.display = 'block'
|
||||
})
|
||||
|
||||
// 点击 忘记密码 去登录 切换div
|
||||
@ -761,14 +769,10 @@
|
||||
|
||||
// 忘记密码
|
||||
document.querySelector('#goChangePassword').addEventListener('click', function () {
|
||||
|
||||
btnList.style.display = 'none'
|
||||
change.style.display = 'block'
|
||||
dengLu.style.display = 'none'
|
||||
changePassword.style.display = 'block'
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
// 去登录
|
||||
|
Loading…
Reference in New Issue
Block a user