mirror of
https://gitee.com/gz-yami/mall4j.git
synced 2026-03-22 09:17:16 +08:00
登录验证在security中确定方法,在admin和api中确定实现,不在使用url中的grant_type来确定
This commit is contained in:
@@ -14,14 +14,14 @@ package com.yami.shop.security.config;
|
||||
import com.yami.shop.security.filter.LoginAuthenticationFilter;
|
||||
import com.yami.shop.security.handler.LoginAuthFailedHandler;
|
||||
import com.yami.shop.security.handler.LoginAuthSuccessHandler;
|
||||
import com.yami.shop.security.provider.AdminAuthenticationProvider;
|
||||
import com.yami.shop.security.provider.MiniAppAuthenticationProvider;
|
||||
import com.yami.shop.security.provider.AuthenticationTokenParser;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
@@ -39,10 +39,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
private LoginAuthFailedHandler loginAuthFailedHandler;
|
||||
|
||||
@Autowired
|
||||
private AdminAuthenticationProvider adminAuthenticationProvider;
|
||||
private AuthenticationProvider authenticationProvider;
|
||||
|
||||
@Autowired
|
||||
private MiniAppAuthenticationProvider miniAppAuthenticationProvider;
|
||||
private AuthenticationTokenParser authenticationTokenParser;
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
@@ -57,8 +57,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
*/
|
||||
@Override
|
||||
public void configure(AuthenticationManagerBuilder auth) {
|
||||
auth.authenticationProvider(adminAuthenticationProvider);
|
||||
auth.authenticationProvider(miniAppAuthenticationProvider);
|
||||
auth.authenticationProvider(authenticationProvider);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -77,6 +76,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
}
|
||||
filter.setAuthenticationSuccessHandler(loginAuthSuccessHandler);
|
||||
filter.setAuthenticationFailureHandler(loginAuthFailedHandler);
|
||||
filter.setAuthenticationTokenParser(authenticationTokenParser);
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,16 +12,11 @@ package com.yami.shop.security.filter;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import com.yami.shop.common.util.Json;
|
||||
import com.yami.shop.security.constants.SecurityConstants;
|
||||
import com.yami.shop.security.exception.UnknownGrantTypeExceptionBase;
|
||||
import com.yami.shop.security.token.AdminAuthenticationToken;
|
||||
import com.yami.shop.security.token.MiniAppAuthenticationToken;
|
||||
import com.yami.shop.security.provider.AuthenticationTokenParser;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.oauth2.common.util.OAuth2Utils;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
import javax.servlet.ServletInputStream;
|
||||
@@ -32,44 +27,28 @@ import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 小程序登陆:此时principal为code
|
||||
* post:http://127.0.0.1:8086/login?grant_type=mini_app
|
||||
* post:http://127.0.0.1:8086/login
|
||||
* {principal:code}
|
||||
* 管理员登陆:
|
||||
* post: http://127.0.0.1:8086/login?grant_type=admin
|
||||
* post: http://127.0.0.1:8086/login
|
||||
* {principal:username,credentials:password}
|
||||
*/
|
||||
public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
|
||||
|
||||
private AuthenticationTokenParser authenticationTokenParser;
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
|
||||
if (!ServletUtil.METHOD_POST.equals(request.getMethod())) {
|
||||
throw new AuthenticationServiceException(
|
||||
"Authentication method not supported: " + request.getMethod());
|
||||
}
|
||||
String type = obtainParameter(request, OAuth2Utils.GRANT_TYPE);
|
||||
|
||||
AbstractAuthenticationToken authRequest = null;
|
||||
|
||||
String requestBody = getStringFromStream(request);
|
||||
|
||||
if (StrUtil.isBlank(requestBody)) {
|
||||
throw new AuthenticationServiceException("无法获取输入信息");
|
||||
}
|
||||
|
||||
// 小程序通过code登陆
|
||||
if(SecurityConstants.SPRING_SECURITY_RESTFUL_TYPE_MINI_APP.equals(type)){
|
||||
authRequest = Json.parseObject(requestBody, MiniAppAuthenticationToken.class);
|
||||
}
|
||||
|
||||
|
||||
// 账号密码登陆
|
||||
else if (SecurityConstants.SPRING_SECURITY_RESTFUL_TYPE_ADMIN.equals(type)) {
|
||||
authRequest = Json.parseObject(requestBody, AdminAuthenticationToken.class);
|
||||
}
|
||||
|
||||
if (authRequest == null) {
|
||||
throw new UnknownGrantTypeExceptionBase("未知的grant_type");
|
||||
}
|
||||
AbstractAuthenticationToken authRequest = authenticationTokenParser.parse(requestBody);
|
||||
|
||||
// Allow subclasses to set the "details" property
|
||||
setDetails(request, authRequest);
|
||||
@@ -81,12 +60,6 @@ public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFil
|
||||
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
|
||||
}
|
||||
|
||||
private String obtainParameter(HttpServletRequest request, String parameter) {
|
||||
String result = request.getParameter(parameter);
|
||||
return result == null ? "" : result;
|
||||
}
|
||||
|
||||
|
||||
private String getStringFromStream(HttpServletRequest req) {
|
||||
ServletInputStream is;
|
||||
try {
|
||||
@@ -106,4 +79,8 @@ public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFil
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public void setAuthenticationTokenParser(AuthenticationTokenParser authenticationTokenParser) {
|
||||
this.authenticationTokenParser = authenticationTokenParser;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
|
||||
*
|
||||
* https://www.gz-yami.com/
|
||||
*
|
||||
* 未经允许,不可做商业用途!
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.yami.shop.security.provider;
|
||||
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yami.shop.common.util.RedisUtil;
|
||||
import com.yami.shop.security.constants.SecurityConstants;
|
||||
import com.yami.shop.security.enums.App;
|
||||
import com.yami.shop.security.exception.BadCredentialsExceptionBase;
|
||||
import com.yami.shop.security.exception.ImageCodeNotMatchExceptionBase;
|
||||
import com.yami.shop.security.exception.UsernameNotFoundExceptionBase;
|
||||
import com.yami.shop.security.exception.BaseYamiAuth2Exception;
|
||||
import com.yami.shop.security.service.YamiUserDetailsService;
|
||||
import com.yami.shop.security.token.AdminAuthenticationToken;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 后台管理员账号密码登陆
|
||||
* @author LGH
|
||||
*/
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class AdminAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
|
||||
|
||||
private final YamiUserDetailsService yamiUserDetailsService;
|
||||
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
@Override
|
||||
protected UserDetails retrieveUser(String username, Authentication authentication) throws BaseYamiAuth2Exception {
|
||||
UserDetails user;
|
||||
try {
|
||||
user = yamiUserDetailsService.loadUserByUsername(username);
|
||||
} catch (UsernameNotFoundExceptionBase var6) {
|
||||
throw new UsernameNotFoundExceptionBase("账号或密码不正确");
|
||||
}
|
||||
if (!user.isEnabled()) {
|
||||
throw new UsernameNotFoundExceptionBase("账号已被锁定,请联系管理员");
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void additionalAuthenticationChecks(UserDetails sysUser, Authentication authentication) throws BaseYamiAuth2Exception {
|
||||
AdminAuthenticationToken adminAuthenticationToken = (AdminAuthenticationToken) authentication;
|
||||
|
||||
String kaptchaKey = SecurityConstants.SPRING_SECURITY_RESTFUL_IMAGE_CODE + adminAuthenticationToken.getSessionUUID();
|
||||
|
||||
String kaptcha = RedisUtil.get(kaptchaKey);
|
||||
|
||||
RedisUtil.del(kaptchaKey);
|
||||
|
||||
if(StrUtil.isBlank(adminAuthenticationToken.getImageCode()) || !adminAuthenticationToken.getImageCode().equalsIgnoreCase(kaptcha)){
|
||||
throw new ImageCodeNotMatchExceptionBase("验证码有误");
|
||||
}
|
||||
|
||||
|
||||
|
||||
String encodedPassword = sysUser.getPassword();
|
||||
String rawPassword = authentication.getCredentials().toString();
|
||||
|
||||
// 密码不正确
|
||||
if (!passwordEncoder.matches(rawPassword,encodedPassword)){
|
||||
throw new BadCredentialsExceptionBase("账号或密码不正确");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Authentication createSuccessAuthentication(Authentication authentication, UserDetails user) {
|
||||
AdminAuthenticationToken result = new AdminAuthenticationToken(user, authentication.getCredentials());
|
||||
result.setDetails(authentication.getDetails());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
return AdminAuthenticationToken.class.isAssignableFrom(authentication);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected App getAppInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.yami.shop.security.provider;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
|
||||
/**
|
||||
* AuthenticationTokenParser
|
||||
*
|
||||
* @author hanfeng
|
||||
* @date 2019-08-21
|
||||
*/
|
||||
public interface AuthenticationTokenParser {
|
||||
AbstractAuthenticationToken parse(String authenticationTokenStr);
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
|
||||
*
|
||||
* https://www.gz-yami.com/
|
||||
*
|
||||
* 未经允许,不可做商业用途!
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.yami.shop.security.provider;
|
||||
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
import com.yami.shop.security.enums.App;
|
||||
import com.yami.shop.security.exception.UsernameNotFoundExceptionBase;
|
||||
import com.yami.shop.security.exception.WxErrorExceptionBase;
|
||||
import com.yami.shop.security.model.AppConnect;
|
||||
import com.yami.shop.security.service.YamiUser;
|
||||
import com.yami.shop.security.service.YamiUserDetailsService;
|
||||
import com.yami.shop.security.token.MiniAppAuthenticationToken;
|
||||
import com.yami.shop.security.token.MyAuthenticationToken;
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 小程序登陆
|
||||
* @author LGH
|
||||
*/
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class MiniAppAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
|
||||
|
||||
private final YamiUserDetailsService yamiUserDetailsService;
|
||||
|
||||
private final WxMaService wxMaService;
|
||||
|
||||
@Override
|
||||
protected void additionalAuthenticationChecks(UserDetails var1, Authentication authentication) throws AuthenticationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Authentication createSuccessAuthentication(Authentication authentication, UserDetails user) {
|
||||
MiniAppAuthenticationToken result = new MiniAppAuthenticationToken(user, authentication.getCredentials());
|
||||
result.setDetails(authentication.getDetails());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UserDetails retrieveUser(String code, Authentication authentication) throws AuthenticationException {
|
||||
YamiUser loadedUser = null;
|
||||
// 如果使用debugger 模式,则返回debugger的用户
|
||||
if (BooleanUtil.isTrue(((MyAuthenticationToken)authentication).getDebugger())) {
|
||||
loadedUser = new YamiUser("1" , "debuggerOpenId1" , this.getAppInfo().value(), true);
|
||||
loadedUser.setDebugger(true);
|
||||
return loadedUser;
|
||||
}
|
||||
|
||||
WxMaJscode2SessionResult session = null;
|
||||
|
||||
AppConnect appConnect = new AppConnect();
|
||||
appConnect.setAppId(this.getAppInfo().value());
|
||||
try {
|
||||
|
||||
session = wxMaService.getUserService().getSessionInfo(code);
|
||||
|
||||
loadedUser = yamiUserDetailsService.loadUserByAppIdAndBizUserId(this.getAppInfo(),session.getOpenid());
|
||||
} catch (WxErrorException e) {
|
||||
throw new WxErrorExceptionBase(e.getMessage());
|
||||
} catch (UsernameNotFoundExceptionBase var6) {
|
||||
if (session == null) {
|
||||
throw new WxErrorExceptionBase("无法获取用户登陆信息");
|
||||
}
|
||||
appConnect.setBizUserId(session.getOpenid());
|
||||
appConnect.setBizUnionid(session.getUnionid());
|
||||
yamiUserDetailsService.insertUserIfNecessary(appConnect);
|
||||
}
|
||||
|
||||
if (loadedUser == null) {
|
||||
loadedUser = yamiUserDetailsService.loadUserByAppIdAndBizUserId(this.getAppInfo(), appConnect.getBizUserId());
|
||||
}
|
||||
return loadedUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
return MiniAppAuthenticationToken.class.isAssignableFrom(authentication);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected App getAppInfo() {
|
||||
return App.MINI;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
|
||||
*
|
||||
* https://www.gz-yami.com/
|
||||
*
|
||||
* 未经允许,不可做商业用途!
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.yami.shop.security.token;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 系统用户账号密码登陆
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class AdminAuthenticationToken extends MyAuthenticationToken {
|
||||
|
||||
private String sessionUUID;
|
||||
|
||||
private String imageCode;
|
||||
|
||||
public AdminAuthenticationToken(UserDetails principal, Object credentials) {
|
||||
super(principal, credentials, principal.getAuthorities());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
|
||||
*
|
||||
* https://www.gz-yami.com/
|
||||
*
|
||||
* 未经允许,不可做商业用途!
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.yami.shop.security.token;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
/**
|
||||
* 二维码Token
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class MiniAppAuthenticationToken extends MyAuthenticationToken {
|
||||
|
||||
|
||||
public MiniAppAuthenticationToken(UserDetails principal, Object credentials) {
|
||||
super(principal, credentials, principal.getAuthorities());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user