|
@ -13,9 +13,9 @@ parent:版本封装<br/>
|
|||
base:功能封装
|
||||
|
||||
#### 最新版本
|
||||
* 1.x yexuejc.springboot.version=1.1.5 <br>
|
||||
* 2.x yexuejc.springboot.version=2.0.4 <br>
|
||||
* yexuejc.base.version=1.2.2
|
||||
* 1.x yexuejc.springboot.version=1.2.0 <br>
|
||||
* 2.x yexuejc.springboot.version=2.0.5 <br>
|
||||
* yexuejc.base.version=1.2.4
|
||||
|
||||
pom.xml
|
||||
```
|
||||
|
|
26
UPDATE.md
|
@ -1,6 +1,32 @@
|
|||
yexuejc-springboot 更新内容
|
||||
-------------------
|
||||
|
||||
#### version :1.2.0
|
||||
**time:2018-12-1 12:19:06** <br/>
|
||||
**branch:** master <br/>
|
||||
**关联工程:** <br/>
|
||||
```
|
||||
springboot-base:1.2.4
|
||||
spring-boot-starter-parent:1.5.16.RELEASE
|
||||
```
|
||||
**update:** <br/>
|
||||
1. security多方登录第一个稳定版<br/>
|
||||
支持账号登录、短信登录、第三方授权openid登录<br/>
|
||||
功能链接[security重构-多方登录](doc/SECURITY.md)
|
||||
#
|
||||
|
||||
#### version :1.1.6-1.1.9
|
||||
**time:2018-11-21 15:03:01** <br/>
|
||||
**branch:** master <br/>
|
||||
**关联工程:** <br/>
|
||||
```
|
||||
springboot-base:1.2.1
|
||||
spring-boot-starter-parent:1.5.16.RELEASE
|
||||
```
|
||||
**update:** <br/>
|
||||
1. security 登录开放处理
|
||||
#
|
||||
|
||||
#### version :1.1.5
|
||||
**time:2018年11月20日20:26:06** <br/>
|
||||
**branch:** master <br/>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
Security框架封装集成登录 使用指南
|
||||
Security框架封装集成多方登录 使用指南
|
||||
-------------
|
||||
#### 先上[效果图](Securtity效果图.md)
|
||||
|
||||
单独使用例子工程:[https://github.com/yexuejc/springboot-security-login-simple](https://github.com/yexuejc/springboot-security-login-simple)
|
||||
* 本项目依赖不向下传递
|
||||
|
||||
|
@ -15,7 +17,8 @@ Security框架封装集成登录 使用指南
|
|||
</dependencies>
|
||||
```
|
||||
> **相关文件说明** 所有核心文件都在 com.yexuejc.springboot.base.security 包下
|
||||
|
||||
#### 现附上系统实现逻辑图
|
||||
![多方登录系统实现逻辑图](多方登录设计.jpg)
|
||||
|
||||
1.com.yexuejc.springboot.base.security.SecurityConfig
|
||||
<br/>
|
||||
|
@ -26,6 +29,38 @@ Security框架封装集成登录 使用指南
|
|||
* 继承configure(HttpSecurity http) 完善更多security过滤配置
|
||||
* 例子[com.yexuejc.springboot.base.security.MySecurityConfig](../yexuejc-springboot-base/src/test/java/com/yexuejc/springboot/base/security/MySecurityConfig.java)
|
||||
|
||||
#### 注: 代码中抛出的相关异常拦截在filter.setAuthenticationFailureHandler()中处理,参考[MySecurityConfig](../yexuejc-springboot-base/src/test/java/com/yexuejc/springboot/base/security/MySecurityConfig.java)
|
||||
```
|
||||
filter.setAuthenticationFailureHandler((request, response, exception) -> {
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
Resps resps = new Resps();
|
||||
if (exception instanceof DisabledException) {
|
||||
resps.setErr(RespsConsts.CODE_FAIL, new String[]{BizConsts.BASE_IS_LOCK_MSG});
|
||||
} else if (exception instanceof AccountExpiredException) {
|
||||
resps.setErr(RespsConsts.CODE_FAIL, new String[]{BizConsts.BASE_IS_EXPIRE_MSG});
|
||||
} else if (exception instanceof CredentialsExpiredException) {
|
||||
resps.setErr(BizConsts.BASE_LOGIN_IS_EXPIRE_CODE, new String[]{BizConsts.BASE_LOGIN_IS_EXPIRE_MSG});
|
||||
} else if (exception instanceof LockedException) {
|
||||
resps.setErr(RespsConsts.CODE_FAIL, new String[]{BizConsts.BASE_IS_LOCKED_MSG});
|
||||
} else if (exception instanceof AuthenticationCredentialsNotFoundException) {
|
||||
resps.setErr(RespsConsts.CODE_FAIL, new String[]{BizConsts.BASE_CREDENTIALS_NOT_FOUND_MSG});
|
||||
} else if (exception instanceof ThirdPartyAuthorizationException) {
|
||||
resps.setErr(RespsConsts.CODE_FAIL, new String[]{exception.getMessage()});
|
||||
} else if (exception instanceof BadCredentialsException) {
|
||||
resps.setErr(RespsConsts.CODE_FAIL, new String[]{BizConsts.BASE_PWD_IS_ERR_MSG});
|
||||
} else if (exception instanceof UsernameNotFoundException) {
|
||||
resps.setErr(RespsConsts.CODE_FAIL, new String[]{BizConsts.BASE_ACCOUNT_NOT_FOUND_MSG});
|
||||
} else if (exception instanceof UserNotAuthoriayException) {
|
||||
resps.setErr(RespsConsts.CODE_FAIL, new String[]{exception.getMessage()});
|
||||
} else {
|
||||
resps.setErr(RespsConsts.CODE_FAIL, new String[]{BizConsts.BASE_SYS_ERR_MSG});
|
||||
}
|
||||
response.getWriter().write(JsonUtil.obj2Json(resps));
|
||||
response.getWriter().close();
|
||||
});
|
||||
```
|
||||
|
||||
2.com.yexuejc.springboot.base.security.UserDetailsManager
|
||||
<br/>
|
||||
**获取登录用户信息**
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
Security 多方登录封装使用效果图
|
||||
---------------
|
||||
### 账号登录
|
||||
密码错误
|
||||
![](sl/sl_02.png)
|
||||
正确
|
||||
![](sl/sl_01.png)
|
||||
|
||||
### 短信登录
|
||||
发送短信
|
||||
![](sl/sl_ss.png)
|
||||
短信错误
|
||||
![](sl/sl_err.jpg)
|
||||
短信过期
|
||||
![](sl/sl_gq.png)
|
||||
正确
|
||||
![](sl/sl_10.png)
|
||||
|
||||
|
||||
### 第三方登录
|
||||
第一次登录,需要绑定手机号
|
||||
![](sl/sl_t3.png)
|
||||
绑定过手机号的第三方账号登录(绑定相关业务需要自己实现)
|
||||
![](sl/sl_t4.png)
|
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 69 KiB |
After Width: | Height: | Size: 240 KiB |
4
pom.xml
|
@ -5,7 +5,7 @@
|
|||
|
||||
<groupId>com.yexuejc.springboot</groupId>
|
||||
<artifactId>yexuejc-springboot-parent</artifactId>
|
||||
<version>1.1.5</version>
|
||||
<version>1.2.0</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
|
@ -20,7 +20,7 @@
|
|||
</parent>
|
||||
|
||||
<properties>
|
||||
<yexuejc.base.version>1.2.2</yexuejc.base.version>
|
||||
<yexuejc.base.version>1.2.4</yexuejc.base.version>
|
||||
<repos.yexuejc.url>https://nexus.yexuejc.club/repository/</repos.yexuejc.url>
|
||||
|
||||
<repos.aliyun.url>http://maven.aliyun.com/nexus/content/groups/public</repos.aliyun.url>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<parent>
|
||||
<groupId>com.yexuejc.springboot</groupId>
|
||||
<artifactId>yexuejc-springboot-parent</artifactId>
|
||||
<version>1.1.5</version>
|
||||
<version>1.2.0</version>
|
||||
<!-- 本地打包:使用相对关联路径 -->
|
||||
<!--<relativePath>../../yexuejc</relativePath>-->
|
||||
</parent>
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package com.yexuejc.springboot.base.exception;
|
||||
|
||||
/**
|
||||
* 类型转换异常
|
||||
*
|
||||
* @author: maxf
|
||||
* @date: 2018/5/12 18:36
|
||||
*/
|
||||
public class ClassConvertExeption extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -2390195902982826130L;
|
||||
/**
|
||||
* 错误码
|
||||
*/
|
||||
private String code = "E";
|
||||
|
||||
public ClassConvertExeption() {
|
||||
super("类型转换异常");
|
||||
}
|
||||
|
||||
public ClassConvertExeption(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -20,37 +20,37 @@ public class ConsumerAuthenticationProcessingFilter extends AbstractAuthenticati
|
|||
// ~ Static fields/initializers
|
||||
// =====================================================================================
|
||||
|
||||
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
|
||||
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
|
||||
protected static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
|
||||
protected static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
|
||||
/**
|
||||
* 登录方式
|
||||
*/
|
||||
public static final String SPRING_SECURITY_FORM_LOGTYPE_KEY = "logtype";
|
||||
public static final String SPRING_SECURITY_FORM_OPENID_KEY = "openid";
|
||||
protected static final String SPRING_SECURITY_FORM_LOGTYPE_KEY = "logtype";
|
||||
protected static final String SPRING_SECURITY_FORM_OPENID_KEY = "openid";
|
||||
/********************************** 第三方登录时附带信息*************************************/
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
public static final String SPRING_SECURITY_FORM_HEAD_KEY = "head";
|
||||
protected static final String SPRING_SECURITY_FORM_HEAD_KEY = "head";
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
public static final String SPRING_SECURITY_FORM_NICKNAME_KEY = "nickname";
|
||||
protected static final String SPRING_SECURITY_FORM_NICKNAME_KEY = "nickname";
|
||||
/**
|
||||
* 性别
|
||||
*/
|
||||
public static final String SPRING_SECURITY_FORM_SEX_KEY = "sex";
|
||||
protected static final String SPRING_SECURITY_FORM_SEX_KEY = "sex";
|
||||
/********************************** 第三方登录时附带信息*************************************/
|
||||
|
||||
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
|
||||
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
|
||||
private String logtypeParameter = SPRING_SECURITY_FORM_LOGTYPE_KEY;
|
||||
private String openidParameter = SPRING_SECURITY_FORM_OPENID_KEY;
|
||||
private String headParameter = SPRING_SECURITY_FORM_HEAD_KEY;
|
||||
private String nicknameParameter = SPRING_SECURITY_FORM_NICKNAME_KEY;
|
||||
private String sexParameter = SPRING_SECURITY_FORM_SEX_KEY;
|
||||
private boolean postOnly = true;
|
||||
private boolean reverse = true;
|
||||
protected String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
|
||||
protected String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
|
||||
protected String logtypeParameter = SPRING_SECURITY_FORM_LOGTYPE_KEY;
|
||||
protected String openidParameter = SPRING_SECURITY_FORM_OPENID_KEY;
|
||||
protected String headParameter = SPRING_SECURITY_FORM_HEAD_KEY;
|
||||
protected String nicknameParameter = SPRING_SECURITY_FORM_NICKNAME_KEY;
|
||||
protected String sexParameter = SPRING_SECURITY_FORM_SEX_KEY;
|
||||
protected boolean postOnly = true;
|
||||
protected boolean reverse = true;
|
||||
|
||||
// ~ Constructors
|
||||
// ===================================================================================================
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.yexuejc.base.pojo.ApiVO;
|
|||
import com.yexuejc.base.util.StrUtil;
|
||||
import com.yexuejc.springboot.base.constant.BizConsts;
|
||||
import com.yexuejc.springboot.base.constant.LogTypeConsts;
|
||||
import com.yexuejc.springboot.base.exception.ClassConvertExeption;
|
||||
import com.yexuejc.springboot.base.exception.ThirdPartyAuthorizationException;
|
||||
import com.yexuejc.springboot.base.security.inte.User;
|
||||
import com.yexuejc.springboot.base.security.inte.UserService;
|
||||
|
@ -50,12 +51,12 @@ public class ConsumerAuthenticationProvider extends AbstractUserDetailsAuthentic
|
|||
* PasswordEncoder#matches(CharSequence, String)} on when the user is
|
||||
* not found to avoid SEC-2056.
|
||||
*/
|
||||
private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";
|
||||
protected static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";
|
||||
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
private PasswordEncoder passwordEncoder;
|
||||
protected PasswordEncoder passwordEncoder;
|
||||
|
||||
/**
|
||||
* The password used to perform
|
||||
|
@ -64,10 +65,10 @@ public class ConsumerAuthenticationProvider extends AbstractUserDetailsAuthentic
|
|||
* {@link PasswordEncoder} implementations will short circuit if the password is not
|
||||
* in a valid format.
|
||||
*/
|
||||
private volatile String userNotFoundEncodedPassword;
|
||||
protected volatile String userNotFoundEncodedPassword;
|
||||
|
||||
private UserDetailsService userDetailsService;
|
||||
private final UserService accountView;
|
||||
protected UserDetailsService userDetailsService;
|
||||
protected final UserService accountView;
|
||||
|
||||
|
||||
public ConsumerAuthenticationProvider(UserDetailsService userDetailsService, UserService accountView) {
|
||||
|
@ -177,46 +178,14 @@ public class ConsumerAuthenticationProvider extends AbstractUserDetailsAuthentic
|
|||
throw notFound;
|
||||
} else {
|
||||
try {
|
||||
//其他方式登录:查询账号 没有->创建账号
|
||||
//第三方登录
|
||||
if (consumerToken != null && StrUtil.isNotEmpty(consumerToken.getOpenid())) {
|
||||
ApiVO apiVO = accountView.checkOpenId(consumerToken);
|
||||
if (apiVO.isSucc()) {
|
||||
//已有账号
|
||||
User consumer = apiVO.getObject1(User.class);
|
||||
// 处理用户权限
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
for (String role : consumer.getRoles()) {
|
||||
authorities.add(new SimpleGrantedAuthority(role));
|
||||
}
|
||||
loadedUser = new ConsumerUser(
|
||||
StrUtil.isEmpty(consumer.getMobile()) ? consumerToken.getOpenid() : consumer.getMobile(),
|
||||
consumer.getPwd(), consumer.getEnable(), consumer.getNonExpire(),
|
||||
true, consumer.getNonLock(), authorities, consumer.getConsumerId(),
|
||||
logtype, System.currentTimeMillis());
|
||||
return loadedUser;
|
||||
}
|
||||
}
|
||||
//第三方登录+短信登录
|
||||
if (consumerToken != null) {
|
||||
//没有->创建账号
|
||||
consumerToken.isReg = true;
|
||||
ApiVO apiVO = accountView.addConsumer(consumerToken);
|
||||
if (apiVO.isSucc()) {
|
||||
loadedUser = display(consumerToken, apiVO.getObject1(User.class));
|
||||
return loadedUser;
|
||||
} else {
|
||||
throw new ThirdPartyAuthorizationException(apiVO.getMsg());
|
||||
}
|
||||
}
|
||||
return third(consumerToken, loadedUser, logtype);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof ThirdPartyAuthorizationException) {
|
||||
throw e;
|
||||
}
|
||||
throw new ThirdPartyAuthorizationException("登录失败,请稍后重试");
|
||||
throw new ThirdPartyAuthorizationException(e.getMessage());
|
||||
}
|
||||
throw notFound;
|
||||
}
|
||||
} catch (Exception repositoryProblem) {
|
||||
throw new InternalAuthenticationServiceException(
|
||||
|
@ -229,13 +198,78 @@ public class ConsumerAuthenticationProvider extends AbstractUserDetailsAuthentic
|
|||
return loadedUser;
|
||||
}
|
||||
|
||||
private void prepareTimingAttackProtection() {
|
||||
/**
|
||||
* 第三方登录处理=>登录用户为空,此方法处理返回登录用户
|
||||
*
|
||||
* @param consumerToken 登录信息
|
||||
* @param loadedUser 登录用户(为空时进入此方法)
|
||||
* @param logtype 登录方式
|
||||
* @return 登录用户
|
||||
*/
|
||||
protected UserDetails third(ConsumerToken consumerToken, UserDetails loadedUser, String logtype) {
|
||||
//其他方式登录:查询账号 没有->创建账号
|
||||
//第三方登录
|
||||
if (consumerToken != null && StrUtil.isNotEmpty(consumerToken.getOpenid())) {
|
||||
Object obj = accountView.checkOpenId(consumerToken);
|
||||
if (obj != null) {
|
||||
|
||||
//已有账号
|
||||
if (obj instanceof User) {
|
||||
User consumer = (User) obj;
|
||||
// 处理用户权限
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
for (String role : consumer.getRoles()) {
|
||||
authorities.add(new SimpleGrantedAuthority(role));
|
||||
}
|
||||
loadedUser = new ConsumerUser(
|
||||
StrUtil.isEmpty(consumer.getMobile()) ? consumerToken.getOpenid() : consumer.getMobile(),
|
||||
consumer.getPwd(), consumer.getEnable(), consumer.getNonExpire(),
|
||||
true, consumer.getNonLock(), authorities, consumer.getConsumerId(),
|
||||
logtype, System.currentTimeMillis());
|
||||
return loadedUser;
|
||||
} else if (obj instanceof UserDetails) {
|
||||
loadedUser = (UserDetails) obj;
|
||||
return loadedUser;
|
||||
} else {
|
||||
throw new ClassConvertExeption("获取登录用户信息返回结果类型必须是com.yexuejc.springboot.base.security.inte.User实现类" +
|
||||
"或者org.springframework.security.core.userdetails.UserDetails实现类" +
|
||||
"或者com.yexuejc.springboot.base.security.ConsumerUser继承类");
|
||||
}
|
||||
}
|
||||
}
|
||||
//第三方登录+短信登录
|
||||
if (consumerToken != null) {
|
||||
//没有->创建账号
|
||||
consumerToken.isReg = true;
|
||||
Object obj = accountView.addConsumer(consumerToken);
|
||||
if (obj != null) {
|
||||
if (obj instanceof User) {
|
||||
User consumer = (User) obj;
|
||||
loadedUser = display(consumerToken, consumer);
|
||||
return loadedUser;
|
||||
} else if (obj instanceof UserDetails) {
|
||||
loadedUser = (UserDetails) obj;
|
||||
return loadedUser;
|
||||
} else {
|
||||
throw new ClassConvertExeption("获取登录用户信息返回结果类型必须是com.yexuejc.springboot.base.security.inte.User实现类" +
|
||||
"或者org.springframework.security.core.userdetails.UserDetails实现类" +
|
||||
"或者com.yexuejc.springboot.base.security.ConsumerUser继承类");
|
||||
}
|
||||
} else {
|
||||
throw new ThirdPartyAuthorizationException("第三方登录失败");
|
||||
}
|
||||
} else {
|
||||
throw new ThirdPartyAuthorizationException();
|
||||
}
|
||||
}
|
||||
|
||||
protected void prepareTimingAttackProtection() {
|
||||
if (this.userNotFoundEncodedPassword == null) {
|
||||
this.userNotFoundEncodedPassword = this.passwordEncoder.encode(USER_NOT_FOUND_PASSWORD);
|
||||
}
|
||||
}
|
||||
|
||||
private void mitigateAgainstTimingAttack(UsernamePasswordAuthenticationToken authentication) {
|
||||
protected void mitigateAgainstTimingAttack(UsernamePasswordAuthenticationToken authentication) {
|
||||
if (authentication.getCredentials() != null) {
|
||||
String presentedPassword = authentication.getCredentials().toString();
|
||||
this.passwordEncoder.matches(presentedPassword, "{MD5}" + this.userNotFoundEncodedPassword);
|
||||
|
@ -249,7 +283,7 @@ public class ConsumerAuthenticationProvider extends AbstractUserDetailsAuthentic
|
|||
* @param consumer 实际用户信息
|
||||
* @return response User
|
||||
*/
|
||||
private UserDetails display(ConsumerToken consumerToken, User consumer) {
|
||||
protected UserDetails display(ConsumerToken consumerToken, User consumer) {
|
||||
// 处理用户权限
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
for (String role : consumer.getRoles()) {
|
||||
|
|
|
@ -34,10 +34,10 @@ import java.util.Map;
|
|||
*/
|
||||
public class ConsumerSecurityContextRepository implements SecurityContextRepository {
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
private static final String TOKEN = "token";
|
||||
private static final String ROLES = "roles";
|
||||
protected static final String TOKEN = "token";
|
||||
protected static final String ROLES = "roles";
|
||||
|
||||
private final RedisTemplate<Object, Object> redisTemplate0;
|
||||
protected final RedisTemplate<Object, Object> redisTemplate0;
|
||||
|
||||
public ConsumerSecurityContextRepository(RedisTemplate<Object, Object> redisTemplate0) {
|
||||
this.redisTemplate0 = redisTemplate0;
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
package com.yexuejc.springboot.base.security;
|
||||
|
||||
import com.yexuejc.springboot.base.autoconfigure.MutiRedisAutoConfiguration;
|
||||
import com.yexuejc.springboot.base.security.inte.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
|
@ -17,6 +15,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
|||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
@ -39,10 +38,6 @@ public abstract class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@Qualifier(MutiRedisAutoConfiguration.BEAN_REDIS_TEMPLATE0)
|
||||
private RedisTemplate<Object, Object> redisTemplate0;
|
||||
|
||||
|
||||
@Bean
|
||||
public static NoOpPasswordEncoder passwordEncoder() {
|
||||
|
@ -58,22 +53,51 @@ public abstract class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
UserDetailsService userDetailsService = new UserDetailsManager(getUserService());
|
||||
auth.authenticationProvider(new ConsumerAuthenticationProvider(userDetailsService, getUserService()));
|
||||
UserDetailsService userDetailsService = createUserDetailsManager();
|
||||
AuthenticationProvider authenticationProvider = createConsumerAuthenticationProvider(userDetailsService);
|
||||
auth.authenticationProvider(authenticationProvider);
|
||||
auth.userDetailsService(userDetailsService);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 AuthenticationProvider
|
||||
*
|
||||
* @param userDetailsService
|
||||
* @return
|
||||
*/
|
||||
protected AuthenticationProvider createConsumerAuthenticationProvider(UserDetailsService userDetailsService) {
|
||||
return new ConsumerAuthenticationProvider(userDetailsService, getUserService());
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 UserDetailsService
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected UserDetailsService createUserDetailsManager() {
|
||||
return new UserDetailsManager(getUserService());
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public ConsumerAuthenticationProcessingFilter consumerAuthenticationProcessingFilter(
|
||||
AuthenticationManager authenticationManager) throws Exception {
|
||||
ConsumerAuthenticationProcessingFilter filter = new ConsumerAuthenticationProcessingFilter
|
||||
(authenticationManager);
|
||||
ConsumerAuthenticationProcessingFilter filter = createConsumerAuthenticationProcessingFilter(authenticationManager);
|
||||
filter.setAuthenticationManager(this.authenticationManager());
|
||||
loginHodler(filter);
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 ConsumerAuthenticationProcessingFilter
|
||||
*
|
||||
* @param authenticationManager
|
||||
* @return
|
||||
*/
|
||||
protected ConsumerAuthenticationProcessingFilter createConsumerAuthenticationProcessingFilter(AuthenticationManager authenticationManager) {
|
||||
return new ConsumerAuthenticationProcessingFilter(authenticationManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 处理登录
|
||||
|
@ -88,8 +112,7 @@ public abstract class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
|
||||
@Bean
|
||||
public LoginUrlAuthenticationEntryPoint loginUrlAuthenticationEntryPoint() {
|
||||
LoginUrlAuthenticationEntryPoint loginUrlAuthenticationEntryPoint = new LoginUrlAuthenticationEntryPoint
|
||||
("/login");
|
||||
LoginUrlAuthenticationEntryPoint loginUrlAuthenticationEntryPoint = new LoginUrlAuthenticationEntryPoint("/login");
|
||||
return loginUrlAuthenticationEntryPoint;
|
||||
}
|
||||
|
||||
|
@ -134,7 +157,7 @@ public abstract class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
.cors()
|
||||
.and().servletApi().disable()
|
||||
.requestCache().disable()
|
||||
.securityContext().securityContextRepository(new ConsumerSecurityContextRepository(redisTemplate0))
|
||||
.securityContext().securityContextRepository(createConsumerSecurityContextRepository())
|
||||
.and()
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||
|
||||
|
@ -142,6 +165,22 @@ public abstract class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 SecurityContextRepository
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected SecurityContextRepository createConsumerSecurityContextRepository() {
|
||||
return new ConsumerSecurityContextRepository(getRedisDB());
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化放置用户信息的reids库
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract RedisTemplate<Object, Object> getRedisDB();
|
||||
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.yexuejc.springboot.base.security;
|
||||
|
||||
import com.yexuejc.base.util.StrUtil;
|
||||
import com.yexuejc.springboot.base.exception.ClassConvertExeption;
|
||||
import com.yexuejc.springboot.base.exception.UserNotAuthoriayException;
|
||||
import com.yexuejc.springboot.base.security.inte.User;
|
||||
import com.yexuejc.springboot.base.security.inte.UserService;
|
||||
|
@ -23,7 +24,7 @@ import java.util.List;
|
|||
*/
|
||||
public class UserDetailsManager extends InMemoryUserDetailsManager {
|
||||
|
||||
private final UserService userService;
|
||||
protected final UserService userService;
|
||||
|
||||
public UserDetailsManager(UserService userService) {
|
||||
this.userService = userService;
|
||||
|
@ -31,22 +32,34 @@ public class UserDetailsManager extends InMemoryUserDetailsManager {
|
|||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
User consumer = userService.getConsumerByUserName(username);
|
||||
if (StrUtil.isEmpty(consumer)) {
|
||||
throw new UsernameNotFoundException(username);
|
||||
return loadUser(username);
|
||||
}
|
||||
|
||||
protected ConsumerUser loadUser(String username) throws UsernameNotFoundException{
|
||||
Object user = userService.getConsumerByUserName(username);
|
||||
if (user instanceof User) {
|
||||
User consumer = (User) user;
|
||||
if (StrUtil.isEmpty(consumer)) {
|
||||
throw new UsernameNotFoundException(username);
|
||||
}
|
||||
// 处理用户权限
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
if (StrUtil.isEmpty(consumer.getRoles())) {
|
||||
throw new UserNotAuthoriayException("用户" + username + "缺少权限");
|
||||
}
|
||||
for (String role : consumer.getRoles()) {
|
||||
authorities.add(new SimpleGrantedAuthority(role));
|
||||
}
|
||||
ConsumerUser consumerUser = new ConsumerUser(consumer.getMobile(), consumer.getPwd(),
|
||||
consumer.getEnable(), consumer.getNonExpire(), true, consumer.getNonLock(),
|
||||
authorities, consumer.getConsumerId(), null, System.currentTimeMillis());
|
||||
return consumerUser;
|
||||
} else if (user instanceof ConsumerUser) {
|
||||
return (ConsumerUser) user;
|
||||
} else {
|
||||
throw new ClassConvertExeption("获取登录用户信息返回结果类型必须是com.yexuejc.springboot.base.security.inte.User实现类" +
|
||||
"或者com.yexuejc.springboot.base.security.ConsumerUser继承类");
|
||||
}
|
||||
// 处理用户权限
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
if (StrUtil.isEmpty(consumer.getRoles())) {
|
||||
throw new UserNotAuthoriayException("用户" + username + "缺少权限");
|
||||
}
|
||||
for (String role : consumer.getRoles()) {
|
||||
authorities.add(new SimpleGrantedAuthority(role));
|
||||
}
|
||||
ConsumerUser consumerUser = new ConsumerUser(consumer.getMobile(), consumer.getPwd(),
|
||||
consumer.getEnable(), consumer.getNonExpire(), true, consumer.getNonLock(),
|
||||
authorities, consumer.getConsumerId(), null, System.currentTimeMillis());
|
||||
return consumerUser;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.yexuejc.springboot.base.security.inte;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 登录用户接口
|
||||
*
|
||||
* @author maxf
|
||||
* @version 1.0
|
||||
* @ClassName User
|
||||
|
|
|
@ -2,9 +2,13 @@ package com.yexuejc.springboot.base.security.inte;
|
|||
|
||||
import com.yexuejc.base.pojo.ApiVO;
|
||||
import com.yexuejc.springboot.base.constant.BizConsts;
|
||||
import com.yexuejc.springboot.base.exception.UserNotAuthoriayException;
|
||||
import com.yexuejc.springboot.base.security.ConsumerToken;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
/**
|
||||
* 用户登录处理接口
|
||||
*
|
||||
* @author maxf
|
||||
* @version 1.0
|
||||
* @ClassName UserService
|
||||
|
@ -14,11 +18,18 @@ import com.yexuejc.springboot.base.security.ConsumerToken;
|
|||
public interface UserService {
|
||||
/**
|
||||
* 根据用户名到数据库查询用户
|
||||
* <p>
|
||||
* <p>
|
||||
* <p>
|
||||
* 获取登录用户信息返回结果类型必须是
|
||||
* {@link com.yexuejc.springboot.base.security.inte.User}实现类<br/>
|
||||
* 或者{@link com.yexuejc.springboot.base.security.ConsumerUser}继承类
|
||||
* </p>
|
||||
*
|
||||
* @param username 登录账号
|
||||
* @return
|
||||
*/
|
||||
User getConsumerByUserName(String username);
|
||||
Object getConsumerByUserName(String username) throws UserNotAuthoriayException, UsernameNotFoundException;
|
||||
|
||||
/**
|
||||
* 校验短信验证码=>短信登录
|
||||
|
@ -32,17 +43,29 @@ public interface UserService {
|
|||
|
||||
/**
|
||||
* 校验第三方登录openid
|
||||
* <p>
|
||||
* 获取登录用户信息返回结果类型必须是
|
||||
* {@link com.yexuejc.springboot.base.security.inte.User}实现类<br/>
|
||||
* 或者{@link org.springframework.security.core.userdetails.UserDetails}实现类<br/>
|
||||
* 或者{@link com.yexuejc.springboot.base.security.ConsumerUser}继承类
|
||||
* </p>
|
||||
*
|
||||
* @param consumerToken 登录信息
|
||||
* @return apiVO.setObject1(User.class) 自己封装登录用户信息
|
||||
* @return 自己封装登录用户信息
|
||||
*/
|
||||
ApiVO checkOpenId(ConsumerToken consumerToken);
|
||||
Object checkOpenId(ConsumerToken consumerToken);
|
||||
|
||||
/**
|
||||
* 没有账号时根据登录信息创建账号
|
||||
* <p>
|
||||
* 获取登录用户信息返回结果类型必须是
|
||||
* {@link com.yexuejc.springboot.base.security.inte.User}实现类<br/>
|
||||
* 或者{@link org.springframework.security.core.userdetails.UserDetails}实现类<br/>
|
||||
* 或者{@link com.yexuejc.springboot.base.security.ConsumerUser}继承类
|
||||
* </p>
|
||||
*
|
||||
* @param consumerToken 登录信息
|
||||
* @return
|
||||
* @return 自己封装登录用户信息
|
||||
*/
|
||||
ApiVO addConsumer(ConsumerToken consumerToken);
|
||||
Object addConsumer(ConsumerToken consumerToken);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,11 @@ public class MySecurityConfig extends SecurityConfig {
|
|||
@Qualifier(MutiRedisAutoConfiguration.BEAN_REDIS_TEMPLATE0)
|
||||
private RedisTemplate<Object, Object> redisTemplate0;
|
||||
|
||||
@Override
|
||||
protected RedisTemplate<Object, Object> getRedisDB() {
|
||||
return redisTemplate0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存登录信息至redis
|
||||
*
|
||||
|
@ -184,4 +189,5 @@ public class MySecurityConfig extends SecurityConfig {
|
|||
response.getWriter().close();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,11 +13,13 @@ import com.yexuejc.springboot.base.constant.LogTypeConsts;
|
|||
import com.yexuejc.springboot.base.exception.ThirdPartyAuthorizationException;
|
||||
import com.yexuejc.springboot.base.mapper.ConsumerMapper;
|
||||
import com.yexuejc.springboot.base.security.domain.Consumer;
|
||||
import com.yexuejc.springboot.base.security.inte.User;
|
||||
import com.yexuejc.springboot.base.security.inte.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -48,14 +50,37 @@ public class UserServiceImpl implements UserService {
|
|||
* @return
|
||||
*/
|
||||
@Override
|
||||
public User getConsumerByUserName(String username) {
|
||||
public Object getConsumerByUserName(String username) {
|
||||
if (StrUtil.isEmpty(username)) {
|
||||
throw new UsernameNotFoundException("username为空,一般是第三方登录来的,直接抛出UsernameNotFoundException就是");
|
||||
}
|
||||
QueryWrapper queryWrapper = new QueryWrapper();
|
||||
queryWrapper.eq("mobile", username);
|
||||
Consumer consumer = consumerMapper.selectOne(queryWrapper);
|
||||
ArrayList roles = new ArrayList<>();
|
||||
if (null == consumer) {
|
||||
/**
|
||||
* 1.抛出UsernameNotFoundException这个异常如果是第三方登录会走 {@link #checkOpenId(ConsumerToken)}
|
||||
* 2.抛出其他Exception可以自己到{@link MySecurityConfig#loginHodler(ConsumerAuthenticationProcessingFilter)}
|
||||
* 里面的filter.setAuthenticationFailureHandler()中做特殊处理
|
||||
*/
|
||||
throw new UsernameNotFoundException("没有该账号相关信息");
|
||||
}
|
||||
//h2不支持json,人为处理角色
|
||||
ArrayList roles = new ArrayList<>();
|
||||
roles.add("ROLE_CONSUMER");
|
||||
consumer.setRoles(roles);
|
||||
return consumer;
|
||||
//1.consumer为User的实现类
|
||||
// return consumer;
|
||||
|
||||
//2. 自己创建ConsumerUser,直接返回
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
for (String role : consumer.getRoles()) {
|
||||
authorities.add(new SimpleGrantedAuthority(role));
|
||||
}
|
||||
ConsumerUser consumerUser = new ConsumerUser(consumer.getMobile(), consumer.getPwd(),
|
||||
consumer.getEnable(), consumer.getNonExpire(), true, consumer.getNonLock(),
|
||||
authorities, consumer.getConsumerId(), null, System.currentTimeMillis());
|
||||
return consumerUser;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,15 +113,14 @@ public class UserServiceImpl implements UserService {
|
|||
}
|
||||
|
||||
/**
|
||||
* 第三方登录
|
||||
* 校验openid 根据自己业务做判断
|
||||
* <br/>
|
||||
* 返回:封装登录用户信息到 apiVO.setObject1(User.class) 自己封装登录用户信息
|
||||
*
|
||||
* @param consumerToken 登录信息
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ApiVO checkOpenId(ConsumerToken consumerToken) {
|
||||
public Object checkOpenId(ConsumerToken consumerToken) {
|
||||
ApiVO apiVO = new ApiVO(ApiVO.STATUS.F, "没有找到用户信息");
|
||||
switch (consumerToken.getLogtype()) {
|
||||
case LogTypeConsts.QQ:
|
||||
|
@ -111,9 +135,89 @@ public class UserServiceImpl implements UserService {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
return apiVO;
|
||||
if (apiVO.isFail()) {
|
||||
/**
|
||||
* 未查到:
|
||||
* 1.返回null会走(数据库没有这个openid[第三方账号]信息)新增流程 {@link #addConsumer(ConsumerToken)}
|
||||
* 2.也可以自己创建一个带有特殊标识的ConsumerUser,然后在 {@link MySecurityConfig#loginHodler(ConsumerAuthenticationProcessingFilter)}
|
||||
* 里面的filter.setAuthenticationSuccessHandler()中做特殊处理 ps:假装登录成功 :)
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
//h2不支持json,人为处理角色
|
||||
ArrayList roles = new ArrayList<>();
|
||||
roles.add("ROLE_CONSUMER");
|
||||
apiVO.getObject1(Consumer.class).setRoles(roles);
|
||||
//根据openid到数据库查到consumer返回
|
||||
return apiVO.getObject1(Consumer.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #checkOpenId(ConsumerToken)} 返回null会走该方法
|
||||
* 没有账号时处理自己的业务,此处必须返回 构造出的登录用户,否则会抛出{@link ThirdPartyAuthorizationException 第三方授权异常}
|
||||
* <br/>
|
||||
*
|
||||
* @param consumerToken 登录信息
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Object addConsumer(ConsumerToken consumerToken) {
|
||||
Consumer consumer = new Consumer();
|
||||
consumer.setConsumerId(StrUtil.genUUID());
|
||||
consumer.setMobile(StrUtil.isNotEmpty(consumerToken.getUsername()) ? consumerToken.getUsername() : consumerToken.getOpenid());
|
||||
consumer.setPwd(StrUtil.toMD5("123456"));
|
||||
consumer.setEnable(true);
|
||||
consumer.setNonExpire(true);
|
||||
consumer.setNonLock(true);
|
||||
List<String> roles = new ArrayList<>();
|
||||
roles.add("ROLE_CONSUMER");
|
||||
consumer.setRoles(roles);
|
||||
switch (consumerToken.getLogtype()) {
|
||||
case LogTypeConsts.SMS:
|
||||
ApiVO apiVO = checkSmsCode2Redis(BizConsts.CONSUMER_LOGIN_SMS, consumerToken.getUsername(),
|
||||
consumerToken.getSmscode());
|
||||
if (apiVO.isFail()) {
|
||||
throw new ThirdPartyAuthorizationException("短信验证码错误");
|
||||
}
|
||||
consumer.setNickname(consumerToken.getUsername());
|
||||
consumer.setHead("/head/def.png");
|
||||
consumer.setRegType(DictRegTypeConsts.DICT_MOBILE);
|
||||
break;
|
||||
case LogTypeConsts.QQ:
|
||||
consumer.setQqId(consumerToken.getOpenid());
|
||||
consumer.setNickname(consumerToken.getNickname());
|
||||
setHeader(consumerToken, consumer, false);
|
||||
setSex(consumerToken, consumer);
|
||||
consumer.setRegType(DictRegTypeConsts.DICT_QQ);
|
||||
break;
|
||||
case LogTypeConsts.WECHAT:
|
||||
consumer.setWechatId(consumerToken.getOpenid());
|
||||
consumer.setNickname(consumerToken.getNickname());
|
||||
setHeader(consumerToken, consumer, false);
|
||||
setSex(consumerToken, consumer);
|
||||
consumer.setRegType(DictRegTypeConsts.DICT_WECHAT);
|
||||
break;
|
||||
case LogTypeConsts.WEIBO:
|
||||
consumer.setWeiboId(consumerToken.getOpenid());
|
||||
consumer.setNickname(consumerToken.getNickname());
|
||||
setHeader(consumerToken, consumer, false);
|
||||
setSex(consumerToken, consumer);
|
||||
consumer.setRegType(DictRegTypeConsts.DICT_WEIBO);
|
||||
break;
|
||||
default:
|
||||
throw new ThirdPartyAuthorizationException("暂不支持该第三方授权");
|
||||
}
|
||||
Integer result = consumerMapper.insert(consumer);
|
||||
if (result < 1) {
|
||||
/**
|
||||
* 会抛出{@link ThirdPartyAuthorizationException 第三方授权异常}
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
return consumer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 第三方登录 QQ登录
|
||||
*
|
||||
|
@ -173,69 +277,6 @@ public class UserServiceImpl implements UserService {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* 没有账号时处理自己的业务,此次必须返回 构造出的登录用户,否则会抛出{@link ThirdPartyAuthorizationException 第三方授权异常}
|
||||
* <br/>
|
||||
* 返回:封装登录用户信息到 apiVO.setObject1(User.class) 自己封装登录用户信息
|
||||
*
|
||||
* @param consumerToken 登录信息
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ApiVO addConsumer(ConsumerToken consumerToken) {
|
||||
Consumer consumer = new Consumer();
|
||||
consumer.setConsumerId(StrUtil.genUUID());
|
||||
consumer.setMobile(StrUtil.isNotEmpty(consumerToken.getUsername()) ? consumerToken.getUsername() : consumerToken.getOpenid());
|
||||
consumer.setPwd(StrUtil.toMD5("123456"));
|
||||
consumer.setEnable(true);
|
||||
consumer.setNonExpire(true);
|
||||
consumer.setNonLock(true);
|
||||
List<String> roles = new ArrayList<>();
|
||||
roles.add("ROLE_CONSUMER");
|
||||
consumer.setRoles(roles);
|
||||
switch (consumerToken.getLogtype()) {
|
||||
case LogTypeConsts.SMS:
|
||||
ApiVO apiVO = checkSmsCode2Redis(BizConsts.CONSUMER_LOGIN_SMS, consumerToken.getUsername(),
|
||||
consumerToken.getSmscode());
|
||||
if (apiVO.isFail()) {
|
||||
return apiVO;
|
||||
}
|
||||
consumer.setNickname(consumerToken.getUsername());
|
||||
consumer.setHead("/head/def.png");
|
||||
consumer.setRegType(DictRegTypeConsts.DICT_MOBILE);
|
||||
break;
|
||||
case LogTypeConsts.QQ:
|
||||
consumer.setQqId(consumerToken.getOpenid());
|
||||
consumer.setNickname(consumerToken.getNickname());
|
||||
setHeader(consumerToken, consumer, false);
|
||||
setSex(consumerToken, consumer);
|
||||
consumer.setRegType(DictRegTypeConsts.DICT_QQ);
|
||||
break;
|
||||
case LogTypeConsts.WECHAT:
|
||||
consumer.setWechatId(consumerToken.getOpenid());
|
||||
consumer.setNickname(consumerToken.getNickname());
|
||||
setHeader(consumerToken, consumer, false);
|
||||
setSex(consumerToken, consumer);
|
||||
consumer.setRegType(DictRegTypeConsts.DICT_WECHAT);
|
||||
break;
|
||||
case LogTypeConsts.WEIBO:
|
||||
consumer.setWeiboId(consumerToken.getOpenid());
|
||||
consumer.setNickname(consumerToken.getNickname());
|
||||
setHeader(consumerToken, consumer, false);
|
||||
setSex(consumerToken, consumer);
|
||||
consumer.setRegType(DictRegTypeConsts.DICT_WEIBO);
|
||||
break;
|
||||
default:
|
||||
return new ApiVO(ApiVO.STATUS.F, "暂不支持的登录方式");
|
||||
}
|
||||
Integer result = consumerMapper.insert(consumer);
|
||||
if (result < 1) {
|
||||
return new ApiVO(ApiVO.STATUS.F, RespsConsts.CODE_FAIL, "登录失败");
|
||||
}
|
||||
return new ApiVO(ApiVO.STATUS.S).setObject1(consumer);
|
||||
}
|
||||
|
||||
|
||||
public Consumer getConsumerByQQOpenid(String openid) {
|
||||
QueryWrapper queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("qq_id", openid);
|
||||
|
|
|
@ -238,6 +238,7 @@ public class Consumer extends Model<Consumer> implements User {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
package com.yexuejc.springboot.base.web;
|
||||
|
||||
import com.yexuejc.base.http.Resps;
|
||||
import com.yexuejc.base.pojo.ApiVO;
|
||||
import com.yexuejc.base.util.RegexUtil;
|
||||
import com.yexuejc.base.util.StrUtil;
|
||||
import com.yexuejc.springboot.base.autoconfigure.MutiRedisAutoConfiguration;
|
||||
import com.yexuejc.springboot.base.constant.BizConsts;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Security 登录注册相关controller
|
||||
|
@ -19,5 +35,49 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
@RestController
|
||||
public class SecurityCtrl {
|
||||
|
||||
@Autowired
|
||||
@Qualifier(MutiRedisAutoConfiguration.BEAN_REDIS_TEMPLATE1)
|
||||
RedisTemplate<Object, Object> redisTemplate;
|
||||
|
||||
/**
|
||||
* 登录发送短信
|
||||
*
|
||||
* @param mobile
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/login/{mobile}", method = RequestMethod.POST)
|
||||
public Resps login(@PathVariable String mobile) {
|
||||
if (!RegexUtil.regex(mobile, RegexUtil.REGEX_MOBILE)) {
|
||||
return Resps.fail("手机号不正确");
|
||||
}
|
||||
ApiVO apiVO = sendSmsCode(BizConsts.CONSUMER_LOGIN_SMS, mobile);
|
||||
if (apiVO.isFail()) {
|
||||
return Resps.fail(apiVO.getMsg());
|
||||
}
|
||||
return Resps.success(apiVO.getMsg());
|
||||
}
|
||||
|
||||
private ApiVO sendSmsCode(String smsType, String mobile) {
|
||||
String smsId = StrUtil.genUUID(30);
|
||||
String code = StrUtil.genNum().substring(2, 8);
|
||||
//自己接入短信发送
|
||||
boolean result = true;
|
||||
if (result) {
|
||||
//成功
|
||||
//存reids
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("smsId", smsId);
|
||||
map.put("code", code);
|
||||
map.put("trade_id", "短信返回id");
|
||||
map.put("validatedNums", 0);
|
||||
redisTemplate.afterPropertiesSet();
|
||||
redisTemplate.opsForHash().putAll(smsType + "." + mobile, map);
|
||||
// 过期时间:5分钟
|
||||
redisTemplate.expire(smsType + "." + mobile, 5 * 60, TimeUnit.SECONDS);
|
||||
return new ApiVO(ApiVO.STATUS.S, "短信发送成功");
|
||||
} else {
|
||||
return new ApiVO(ApiVO.STATUS.F, "短信发送失败");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|