183 lines
7.8 KiB
Java
183 lines
7.8 KiB
Java
package com.yexuejc.springboot.base.security;
|
||
|
||
import com.yexuejc.base.http.Resps;
|
||
import com.yexuejc.base.util.JsonUtil;
|
||
import com.yexuejc.base.util.JwtUtil;
|
||
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 com.yexuejc.springboot.base.constant.RespsCode;
|
||
import com.yexuejc.springboot.base.http.ResponseParams;
|
||
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.http.HttpStatus;
|
||
import org.springframework.security.authentication.*;
|
||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||
import org.springframework.security.core.GrantedAuthority;
|
||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||
|
||
import java.util.*;
|
||
import java.util.concurrent.TimeUnit;
|
||
|
||
/**
|
||
* @author maxf
|
||
* @version 1.0
|
||
* @ClassName SecurityConfig
|
||
* @Description
|
||
* @date 2018/11/8 17:30
|
||
*/
|
||
@EnableWebSecurity(debug = false)
|
||
public class MySecurityConfig extends SecurityConfig {
|
||
|
||
@Autowired
|
||
@Qualifier("userserviceimpl")
|
||
UserService userService;
|
||
|
||
@Override
|
||
protected UserService getUserService() {
|
||
return userService;
|
||
}
|
||
|
||
@Autowired
|
||
@Qualifier(MutiRedisAutoConfiguration.BEAN_REDIS_TEMPLATE0)
|
||
private RedisTemplate<Object, Object> redisTemplate0;
|
||
|
||
@Override
|
||
protected RedisTemplate<Object, Object> getRedisDB() {
|
||
return redisTemplate0;
|
||
}
|
||
|
||
/**
|
||
* 保存登录信息至redis
|
||
*
|
||
* @param redisTemplate0 redis 链接
|
||
* @param user 登录用户
|
||
* @param roles 角色信息
|
||
* @param token 登录token
|
||
* @param isPast 是否设置过期
|
||
*/
|
||
private void saveLoginUser(RedisTemplate<Object, Object> redisTemplate0, ConsumerUser user, List<String> roles, String token,
|
||
boolean isPast) {
|
||
Map<String, Object> m = new HashMap<>(4);
|
||
m.put("username", user.getUsername());
|
||
m.put("token", token);
|
||
m.put("roles", roles);
|
||
m.put("id", user.getId());
|
||
m.put("logType", user.getLogType());
|
||
m.put("logTime", user.getLogTime());
|
||
redisTemplate0.opsForHash().putAll(BizConsts.CONSUMER_LOGIN_REDIS + "." + user.getUsername(), m);
|
||
if (isPast) {
|
||
//对于没有绑定手机号的token,10分钟后过期
|
||
redisTemplate0.expire(BizConsts.CONSUMER_LOGIN_REDIS + "." + user.getUsername(), 10, TimeUnit.MINUTES);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* <pre>
|
||
* 处理登录
|
||
* 成功: filter.setAuthenticationSuccessHandler()
|
||
* 失败: filter.setAuthenticationFailureHandler()
|
||
* </pre>
|
||
*
|
||
* @param filter
|
||
*/
|
||
@Override
|
||
protected void loginHodler(ConsumerAuthenticationProcessingFilter filter) {
|
||
filter.setAuthenticationSuccessHandler((request, response, authentication) -> {
|
||
String token = JwtUtil.instace().compact(new LoginToken(authentication.getName()));
|
||
ConsumerUser user = (ConsumerUser) authentication.getPrincipal();
|
||
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
|
||
List<String> roles = new ArrayList<>();
|
||
if (authorities != null && authorities.size() > 0) {
|
||
for (GrantedAuthority g : authorities) {
|
||
roles.add(g.getAuthority());
|
||
}
|
||
}
|
||
Map<String, Object> map = new HashMap<>(2);
|
||
map.put("token", token);
|
||
map.put("bindMobile", false);
|
||
if (StrUtil.isEmpty(user.getUsername()) || !RegexUtil.regex(user.getUsername(), RegexUtil.REGEX_MOBILE)) {
|
||
map.put("bindMobile", true);
|
||
}
|
||
saveLoginUser(redisTemplate0, user, roles, token, (Boolean) map.get("bindMobile"));
|
||
response.setContentType("application/json;charset=UTF-8");
|
||
response.getWriter().write(JsonUtil.obj2Json(Resps.success().setSucc(map)));
|
||
response.getWriter().close();
|
||
});
|
||
filter.setAuthenticationFailureHandler((request, response, exception) -> {
|
||
response.setContentType("application/json;charset=UTF-8");
|
||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||
ResponseParams resps;
|
||
if (exception instanceof DisabledException) {
|
||
resps = ResponseParams.resps(RespsCode.INS_AUTH).setSub(RespsCode.IA_IS_LOCK);
|
||
} else if (exception instanceof AccountExpiredException) {
|
||
resps = ResponseParams.resps(RespsCode.INS_AUTH).setSub(RespsCode.IA_IS_EXPIRE);
|
||
} else if (exception instanceof CredentialsExpiredException) {
|
||
resps = ResponseParams.resps(RespsCode.INS_AUTH).setSub(RespsCode.IA_LOGIN_IS_EXPIRE);
|
||
} else if (exception instanceof LockedException) {
|
||
resps = ResponseParams.resps(RespsCode.INS_AUTH).setSub(RespsCode.IA_IS_LOCKED);
|
||
} else if (exception instanceof AuthenticationCredentialsNotFoundException) {
|
||
resps = ResponseParams.resps(RespsCode.INS_AUTH).setSub(RespsCode.IA_CREDENTIALS_NOT_FOUND);
|
||
} else if (exception instanceof BadCredentialsException) {
|
||
resps = ResponseParams.resps(RespsCode.BIZ_ERR).setSub(RespsCode.BE_PWD_IS_ERR);
|
||
} else if (exception instanceof UsernameNotFoundException) {
|
||
resps = ResponseParams.resps(RespsCode.BIZ_ERR).setSub(RespsCode.BE_NOT_FOUND);
|
||
} else {
|
||
resps = ResponseParams.resps(RespsCode.INS_AUTH);
|
||
}
|
||
response.getWriter().write(JsonUtil.obj2Json(resps));
|
||
response.getWriter().close();
|
||
});
|
||
}
|
||
|
||
@Override
|
||
protected void configure(HttpSecurity http) throws Exception {
|
||
super.configure(http);
|
||
http.headers().frameOptions().disable();
|
||
/**
|
||
* 权限控制
|
||
* ->无权限
|
||
*/
|
||
http.authorizeRequests().antMatchers(
|
||
"/", "/index"
|
||
).permitAll();
|
||
|
||
/**
|
||
* 权限控制
|
||
* ->登录可访问
|
||
*/
|
||
http.authorizeRequests().antMatchers(
|
||
"/consumer/**", "/sms/bind/**").authenticated();
|
||
|
||
// 登出处理。
|
||
http.logout().logoutSuccessHandler((request, response, authentication) -> {
|
||
redisTemplate0.delete(BizConsts.CONSUMER_LOGIN_REDIS + "." + authentication.getName());
|
||
response.setContentType("application/json;charset=UTF-8");
|
||
response.getWriter().write(JsonUtil.obj2Json(Resps.success()));
|
||
response.getWriter().close();
|
||
});
|
||
|
||
// 未登录,却访问需要登录的接口时的处理
|
||
http.exceptionHandling().authenticationEntryPoint((request, response, authException) -> {
|
||
response.setContentType("application/json;charset=UTF-8");
|
||
response.setStatus(401);
|
||
response.getWriter().write(
|
||
ResponseParams.resps(RespsCode.PERMISSION_DENIED, RespsCode.PD_NOT_LOGIN).toString());
|
||
response.getWriter().close();
|
||
});
|
||
// 已登录,但当前用户没有访问的某个接口的权限时的处理
|
||
http.exceptionHandling().accessDeniedHandler((request, response, accessDeniedException) -> {
|
||
response.setContentType("application/json;charset=UTF-8");
|
||
response.setStatus(401);
|
||
response.getWriter().write(
|
||
ResponseParams.resps(RespsCode.PERMISSION_DENIED, RespsCode.PD_NOT_LOGIN).toString());
|
||
response.getWriter().close();
|
||
});
|
||
}
|
||
|
||
}
|