Commit 284c25a1 authored by dqjdda's avatar dqjdda
Browse files

Merge branch '2.4dev' into 2.4opt

parents 175a2eb6 ccca30fc
package me.zhengjie.modules.security.security;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Zheng Jie
*/
@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
//当用户在没有授权的情况下访问受保护的REST资源时,将调用此方法发送403 Forbidden响应
response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
}
}
......@@ -13,9 +13,7 @@ import java.io.Serializable;
* @author Zheng Jie
*/
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
private static final long serialVersionUID = -8970718410437077606L;
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request,
......
package me.zhengjie.modules.security.security;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.security.utils.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Zheng Jie
*/
@Slf4j
@Component
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
@Value("${jwt.online}")
private String onlineKey;
private final UserDetailsService userDetailsService;
private final JwtTokenUtil jwtTokenUtil;
private final RedisTemplate redisTemplate;
public JwtAuthorizationTokenFilter(@Qualifier("jwtUserDetailsServiceImpl") UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil, RedisTemplate redisTemplate) {
this.userDetailsService = userDetailsService;
this.jwtTokenUtil = jwtTokenUtil;
this.redisTemplate = redisTemplate;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
String authToken = jwtTokenUtil.getToken(request);
OnlineUser onlineUser = null;
try {
onlineUser = (OnlineUser)redisTemplate.opsForValue().get(onlineKey + authToken);
} catch (ExpiredJwtException e) {
log.error(e.getMessage());
}
if (onlineUser != null && SecurityContextHolder.getContext().getAuthentication() == null) {
// It is not compelling necessary to load the use details from the database. You could also store the information
// in the token and read it from it. It's up to you ;)
JwtUser userDetails = (JwtUser)this.userDetailsService.loadUserByUsername(onlineUser.getUserName());
// For simple validation it is completely sufficient to just check the token integrity. You don't have to call
// the database compellingly. Again it's up to you ;)
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
}
package me.zhengjie.modules.security.security;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/**
* @author /
*/
public class TokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final TokenProvider tokenProvider;
public TokenConfigurer(TokenProvider tokenProvider){
this.tokenProvider = tokenProvider;
}
@Override
public void configure(HttpSecurity http) {
TokenFilter customFilter = new TokenFilter(tokenProvider);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
package me.zhengjie.modules.security.security;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.security.config.SecurityProperties;
import me.zhengjie.modules.security.security.vo.OnlineUser;
import me.zhengjie.modules.security.service.OnlineUserService;
import me.zhengjie.utils.SpringContextHolder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @author /
*/
@Slf4j
public class TokenFilter extends GenericFilterBean {
private final TokenProvider tokenProvider;
TokenFilter(TokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String token = resolveToken(httpServletRequest);
String requestRri = httpServletRequest.getRequestURI();
// 验证 token 是否存在
OnlineUser onlineUser = null;
try {
SecurityProperties properties = SpringContextHolder.getBean(SecurityProperties.class);
OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class);
onlineUser = onlineUserService.getOne(properties.getOnlineKey() + token);
} catch (ExpiredJwtException e) {
log.error(e.getMessage());
}
if (onlineUser != null && StringUtils.hasText(token) && tokenProvider.validateToken(token)) {
Authentication authentication = tokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
log.debug("set Authentication to security context for '{}', uri: {}", authentication.getName(), requestRri);
} else {
log.debug("no valid JWT token found, uri: {}", requestRri);
}
filterChain.doFilter(servletRequest, servletResponse);
}
private String resolveToken(HttpServletRequest request) {
SecurityProperties properties = SpringContextHolder.getBean(SecurityProperties.class);
String bearerToken = request.getHeader(properties.getHeader());
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(properties.getTokenStartWith())) {
return bearerToken.substring(7);
}
return null;
}
}
package me.zhengjie.modules.security.security;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.security.config.SecurityProperties;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.security.Key;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.stream.Collectors;
/**
* @author /
*/
@Slf4j
@Component
public class TokenProvider implements InitializingBean {
private final SecurityProperties properties;
private static final String AUTHORITIES_KEY = "auth";
private Key key;
public TokenProvider(SecurityProperties properties) {
this.properties = properties;
}
@Override
public void afterPropertiesSet() {
byte[] keyBytes = Decoders.BASE64.decode(properties.getBase64Secret());
this.key = Keys.hmacShaKeyFor(keyBytes);
}
public String createToken(Authentication authentication) {
String authorities = authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(","));
long now = (new Date()).getTime();
Date validity = new Date(now + properties.getTokenValidityInSeconds());
return Jwts.builder()
.setSubject(authentication.getName())
.claim(AUTHORITIES_KEY, authorities)
.signWith(key, SignatureAlgorithm.HS512)
.setExpiration(validity)
.compact();
}
Authentication getAuthentication(String token) {
Claims claims = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(token)
.getBody();
Collection<? extends GrantedAuthority> authorities =
Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
User principal = new User(claims.getSubject(), "", authorities);
return new UsernamePasswordAuthenticationToken(principal, token, authorities);
}
boolean validateToken(String authToken) {
try {
Jwts.parser().setSigningKey(key).parseClaimsJws(authToken);
return true;
} catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
log.info("Invalid JWT signature.");
e.printStackTrace();
} catch (ExpiredJwtException e) {
log.info("Expired JWT token.");
e.printStackTrace();
} catch (UnsupportedJwtException e) {
log.info("Unsupported JWT token.");
e.printStackTrace();
} catch (IllegalArgumentException e) {
log.info("JWT token compact of handler are invalid.");
e.printStackTrace();
}
return false;
}
public String getToken(HttpServletRequest request){
final String requestHeader = request.getHeader(properties.getHeader());
if (requestHeader != null && requestHeader.startsWith(properties.getTokenStartWith())) {
return requestHeader.substring(7);
}
return null;
}
}
package me.zhengjie.modules.security.security;
package me.zhengjie.modules.security.security.vo;
import lombok.Getter;
import lombok.Setter;
......
package me.zhengjie.modules.security.security;
package me.zhengjie.modules.security.security.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
......@@ -18,11 +18,14 @@ import java.util.stream.Collectors;
@AllArgsConstructor
public class JwtUser implements UserDetails {
@JsonIgnore
private final Long id;
private final String username;
private final String nickName;
private final String sex;
@JsonIgnore
private final String password;
......
package me.zhengjie.modules.security.security;
package me.zhengjie.modules.security.security.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
......@@ -16,6 +16,8 @@ public class OnlineUser {
private String userName;
private String nickName;
private String job;
private String browser;
......
package me.zhengjie.modules.security.service;
import me.zhengjie.modules.system.domain.Menu;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.modules.system.repository.RoleRepository;
import me.zhengjie.modules.system.service.dto.UserDto;
import me.zhengjie.utils.StringUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
*/
@Service
@CacheConfig(cacheNames = "role")
public class JwtPermissionServiceImpl {
private final RoleRepository roleRepository;
public JwtPermissionServiceImpl(RoleRepository roleRepository) {
this.roleRepository = roleRepository;
}
/**
* key的名称如有修改,请同步修改 UserServiceImpl 中的 update 方法
* @param user 用户信息
* @return Collection
*/
@Cacheable(key = "'loadPermissionByUser:' + #p0.username")
public Collection<GrantedAuthority> mapToGrantedAuthorities(UserDto user) {
System.out.println("--------------------loadPermissionByUser:" + user.getUsername() + "---------------------");
Set<Role> roles = roleRepository.findByUsers_Id(user.getId());
Set<String> permissions = roles.stream().filter(role -> StringUtils.isNotBlank(role.getPermission())).map(Role::getPermission).collect(Collectors.toSet());
permissions.addAll(
roles.stream().flatMap(role -> role.getMenus().stream())
.filter(menu -> StringUtils.isNotBlank(menu.getPermission()))
.map(Menu::getPermission).collect(Collectors.toSet())
);
return permissions.stream().map(permission -> new SimpleGrantedAuthority(permission))
.collect(Collectors.toList());
}
}
package me.zhengjie.modules.security.service;
import me.zhengjie.modules.security.security.JwtUser;
import me.zhengjie.modules.security.security.OnlineUser;
import me.zhengjie.utils.EncryptUtils;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import me.zhengjie.modules.security.config.SecurityProperties;
import me.zhengjie.modules.security.security.vo.JwtUser;
import me.zhengjie.modules.security.security.vo.OnlineUser;
import me.zhengjie.utils.*;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* @author Zheng Jie
* @Date 2019年10月26日21:56:27
*/
@Service
@SuppressWarnings({"unchecked","all"})
public class OnlineUserService {
@Value("${jwt.expiration}")
private Long expiration;
private final SecurityProperties properties;
private RedisUtils redisUtils;
@Value("${jwt.online}")
private String onlineKey;
private final RedisTemplate redisTemplate;
public OnlineUserService(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
public OnlineUserService(SecurityProperties properties, RedisUtils redisUtils) {
this.properties = properties;
this.redisUtils = redisUtils;
}
/**
* 保存在线用户信息
* @param jwtUser /
* @param token /
* @param request /
*/
public void save(JwtUser jwtUser, String token, HttpServletRequest request){
String job = jwtUser.getDept() + "/" + jwtUser.getJob();
String ip = StringUtils.getIp(request);
......@@ -45,28 +39,38 @@ public class OnlineUserService {
String address = StringUtils.getCityInfo(ip);
OnlineUser onlineUser = null;
try {
onlineUser = new OnlineUser(jwtUser.getUsername(), job, browser , ip, address, EncryptUtils.desEncrypt(token), new Date());
onlineUser = new OnlineUser(jwtUser.getUsername(), jwtUser.getNickName(), job, browser , ip, address, EncryptUtils.desEncrypt(token), new Date());
} catch (Exception e) {
e.printStackTrace();
}
redisTemplate.opsForValue().set(onlineKey + token, onlineUser);
redisTemplate.expire(onlineKey + token,expiration, TimeUnit.MILLISECONDS);
redisUtils.set(properties.getOnlineKey() + token, onlineUser, properties.getTokenValidityInSeconds()/1000);
}
public Page<OnlineUser> getAll(String filter, Pageable pageable){
/**
* 查询全部数据
* @param filter /
* @param pageable /
* @return /
*/
public Map<String,Object> getAll(String filter, Pageable pageable){
List<OnlineUser> onlineUsers = getAll(filter);
return new PageImpl<OnlineUser>(
return PageUtil.toPage(
PageUtil.toPage(pageable.getPageNumber(),pageable.getPageSize(),onlineUsers),
pageable,
onlineUsers.size());
onlineUsers.size()
);
}
/**
* 查询全部数据,不分页
* @param filter /
* @return /
*/
public List<OnlineUser> getAll(String filter){
List<String> keys = new ArrayList<>(redisTemplate.keys(onlineKey + "*"));
List<String> keys = redisUtils.scan(properties.getOnlineKey() + "*");
Collections.reverse(keys);
List<OnlineUser> onlineUsers = new ArrayList<>();
for (String key : keys) {
OnlineUser onlineUser = (OnlineUser) redisTemplate.opsForValue().get(key);
OnlineUser onlineUser = (OnlineUser) redisUtils.get(key);
if(StringUtils.isNotBlank(filter)){
if(onlineUser.toString().contains(filter)){
onlineUsers.add(onlineUser);
......@@ -75,22 +79,35 @@ public class OnlineUserService {
onlineUsers.add(onlineUser);
}
}
Collections.sort(onlineUsers, (o1, o2) -> {
return o2.getLoginTime().compareTo(o1.getLoginTime());
});
onlineUsers.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime()));
return onlineUsers;
}
public void kickOut(String val) throws Exception {
String key = onlineKey + EncryptUtils.desDecrypt(val);
redisTemplate.delete(key);
/**
* 踢出用户
* @param key /
* @throws Exception /
*/
public void kickOut(String key) throws Exception {
key = properties.getOnlineKey() + EncryptUtils.desDecrypt(key);
redisUtils.del(key);
}
/**
* 退出登录
* @param token /
*/
public void logout(String token) {
String key = onlineKey + token;
redisTemplate.delete(key);
String key = properties.getOnlineKey() + token;
redisUtils.del(key);
}
/**
* 导出
* @param all /
* @param response /
* @throws IOException /
*/
public void download(List<OnlineUser> all, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (OnlineUser user : all) {
......@@ -105,4 +122,13 @@ public class OnlineUserService {
}
FileUtil.downloadExcel(list, response);
}
/**
* 查询用户
* @param key /
* @return /
*/
public OnlineUser getOne(String key) {
return (OnlineUser)redisUtils.get(key);
}
}
package me.zhengjie.modules.security.service;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.security.security.JwtUser;
import me.zhengjie.modules.security.security.vo.JwtUser;
import me.zhengjie.modules.system.service.RoleService;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.*;
import org.springframework.security.core.userdetails.UserDetails;
......@@ -15,41 +16,45 @@ import java.util.Optional;
* @author Zheng Jie
* @date 2018-11-22
*/
@Service
@Service("userDetailsService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class JwtUserDetailsServiceImpl implements UserDetailsService {
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserService userService;
private final JwtPermissionServiceImpl permissionService;
private final RoleService roleService;
public JwtUserDetailsServiceImpl(UserService userService, JwtPermissionServiceImpl permissionService) {
public UserDetailsServiceImpl(UserService userService, RoleService roleService) {
this.userService = userService;
this.permissionService = permissionService;
this.roleService = roleService;
}
@Override
public UserDetails loadUserByUsername(String username){
UserDto user = userService.findByName(username);
if (user == null) {
throw new BadRequestException("账号不存在");
} else {
if (!user.getEnabled()) {
throw new BadRequestException("账号未激活");
}
return createJwtUser(user);
}
}
public UserDetails createJwtUser(UserDto user) {
private UserDetails createJwtUser(UserDto user) {
return new JwtUser(
user.getId(),
user.getUsername(),
user.getNickName(),
user.getSex(),
user.getPassword(),
user.getAvatar(),
user.getEmail(),
user.getPhone(),
Optional.ofNullable(user.getDept()).map(DeptSmallDto::getName).orElse(null),
Optional.ofNullable(user.getJob()).map(JobSmallDto::getName).orElse(null),
permissionService.mapToGrantedAuthorities(user),
roleService.mapToGrantedAuthorities(user),
user.getEnabled(),
user.getCreateTime(),
user.getLastPasswordResetTime()
......
package me.zhengjie.modules.security.utils;
import io.jsonwebtoken.*;
import io.jsonwebtoken.impl.DefaultClock;
import me.zhengjie.modules.security.security.JwtUser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
/**
* @author /
*/
@Component
public class JwtTokenUtil implements Serializable {
private static final long serialVersionUID = -3301605591108950415L;
private Clock clock = DefaultClock.INSTANCE;
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
@Value("${jwt.header}")
private String tokenHeader;
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
private Date getIssuedAtDateFromToken(String token) {
return getClaimFromToken(token, Claims::getIssuedAt);
}
private Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(clock.now());
}
private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
return (lastPasswordReset != null && created.before(lastPasswordReset));
}
private Boolean ignoreTokenExpiration(String token) {
// here you specify tokens, for that the expiration is ignored
return false;
}
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>(16);
return doGenerateToken(claims, userDetails.getUsername());
}
private String doGenerateToken(Map<String, Object> claims, String subject) {
final Date createdDate = clock.now();
final Date expirationDate = calculateExpirationDate(createdDate);
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(createdDate)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
final Date created = getIssuedAtDateFromToken(token);
return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset)
&& (!isTokenExpired(token) || ignoreTokenExpiration(token));
}
public String refreshToken(String token) {
final Date createdDate = clock.now();
final Date expirationDate = calculateExpirationDate(createdDate);
final Claims claims = getAllClaimsFromToken(token);
claims.setIssuedAt(createdDate);
claims.setExpiration(expirationDate);
return Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public String getToken(HttpServletRequest request){
final String requestHeader = request.getHeader(tokenHeader);
String startsWith = "Bearer ";
if (requestHeader != null && requestHeader.startsWith(startsWith)) {
return requestHeader.substring(7);
}
return null;
}
public Boolean validateToken(String token, UserDetails userDetails) {
JwtUser user = (JwtUser) userDetails;
final Date created = getIssuedAtDateFromToken(token);
// final Date expiration = getExpirationDateFromToken(token);
// 如果token存在,且token创建日期 > 最后修改密码的日期 则代表token有效
return (!isTokenExpired(token)
&& !isCreatedBeforeLastPasswordReset(created, user.getLastPasswordResetDate())
);
}
private Date calculateExpirationDate(Date createdDate) {
return new Date(createdDate.getTime() + expiration);
}
}
......@@ -32,6 +32,13 @@ public class User implements Serializable {
@Column(unique = true)
private String username;
/** 用户昵称 */
@NotBlank
private String nickName;
/** 性别 */
private String sex;
@OneToOne
@JoinColumn(name = "avatar_id")
private UserAvatar userAvatar;
......
......@@ -5,6 +5,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* @author Zheng Jie
......@@ -36,9 +37,9 @@ public interface MenuRepository extends JpaRepository<Menu, Long>, JpaSpecificat
/**
* 根据角色ID与菜单类型查询菜单
* @param id roleID
* @param roleIds roleIDs
* @param type 类型
* @return /
*/
LinkedHashSet<Menu> findByRoles_IdAndTypeIsNotInOrderBySortAsc(Long id, Integer type);
LinkedHashSet<Menu> findByRoles_IdInAndTypeNotOrderBySortAsc(Set<Long> roleIds, int type);
}
......@@ -7,8 +7,10 @@ import me.zhengjie.aop.log.Log;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.system.service.RoleService;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.RoleQueryCriteria;
import me.zhengjie.modules.system.service.dto.RoleSmallDto;
import me.zhengjie.modules.system.service.dto.UserDto;
import me.zhengjie.utils.SecurityUtils;
import me.zhengjie.utils.ThrowableUtil;
import org.springframework.data.domain.Pageable;
......@@ -36,11 +38,13 @@ import java.util.stream.Collectors;
public class RoleController {
private final RoleService roleService;
private final UserService userService;
private static final String ENTITY_NAME = "role";
public RoleController(RoleService roleService) {
public RoleController(RoleService roleService, UserService userService) {
this.roleService = roleService;
this.userService = userService;
}
@ApiOperation("获取单个role")
......@@ -76,7 +80,8 @@ public class RoleController {
@ApiOperation("获取用户级别")
@GetMapping(value = "/level")
public ResponseEntity getLevel(){
List<Integer> levels = roleService.findByUsersId(SecurityUtils.getUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList());
UserDto user = userService.findByName(SecurityUtils.getUsername());
List<Integer> levels = roleService.findByUsersId(user.getId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList());
return new ResponseEntity<>(Dict.create().set("level", Collections.min(levels)),HttpStatus.OK);
}
......
......@@ -11,6 +11,7 @@ import me.zhengjie.modules.system.domain.vo.UserPassVo;
import me.zhengjie.modules.system.service.DeptService;
import me.zhengjie.modules.system.service.RoleService;
import me.zhengjie.modules.system.service.dto.RoleSmallDto;
import me.zhengjie.modules.system.service.dto.UserDto;
import me.zhengjie.modules.system.service.dto.UserQueryCriteria;
import me.zhengjie.service.VerificationCodeService;
import me.zhengjie.utils.*;
......@@ -20,6 +21,8 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
......@@ -39,17 +42,15 @@ import java.util.stream.Collectors;
@RequestMapping("/api/users")
public class UserController {
private final PasswordEncoder passwordEncoder;
private final UserService userService;
private final DataScope dataScope;
private final DeptService deptService;
private final RoleService roleService;
private final VerificationCodeService verificationCodeService;
public UserController(UserService userService, DataScope dataScope, DeptService deptService, RoleService roleService, VerificationCodeService verificationCodeService) {
public UserController(PasswordEncoder passwordEncoder, UserService userService, DataScope dataScope, DeptService deptService, RoleService roleService, VerificationCodeService verificationCodeService) {
this.passwordEncoder = passwordEncoder;
this.userService = userService;
this.dataScope = dataScope;
this.deptService = deptService;
......@@ -118,12 +119,25 @@ public class UserController {
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("修改用户:个人中心")
@ApiOperation("修改用户:个人中心")
@PutMapping(value = "center")
public ResponseEntity center(@Validated(User.Update.class) @RequestBody User resources){
UserDto userDto = userService.findByName(SecurityUtils.getUsername());
if(!resources.getId().equals(userDto.getId())){
throw new BadRequestException("不能修改他人资料");
}
userService.updateCenter(resources);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("删除用户")
@ApiOperation("删除用户")
@DeleteMapping(value = "/{id}")
@PreAuthorize("@el.check('user:del')")
public ResponseEntity delete(@PathVariable Long id){
Integer currentLevel = Collections.min(roleService.findByUsersId(SecurityUtils.getUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
UserDto user = userService.findByName(SecurityUtils.getUsername());
Integer currentLevel = Collections.min(roleService.findByUsersId(user.getId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
Integer optLevel = Collections.min(roleService.findByUsersId(id).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
if (currentLevel > optLevel) {
......@@ -135,15 +149,15 @@ public class UserController {
@ApiOperation("修改密码")
@PostMapping(value = "/updatePass")
public ResponseEntity updatePass(@RequestBody UserPassVo user){
UserDetails userDetails = SecurityUtils.getUserDetails();
if(!userDetails.getPassword().equals(EncryptUtils.encryptPassword(user.getOldPass()))){
public ResponseEntity updatePass(@RequestBody UserPassVo passVo){
UserDto user = userService.findByName(SecurityUtils.getUsername());
if(!passwordEncoder.matches(passVo.getOldPass(), user.getPassword())){
throw new BadRequestException("修改失败,旧密码错误");
}
if(userDetails.getPassword().equals(EncryptUtils.encryptPassword(user.getNewPass()))){
if(passwordEncoder.matches(passVo.getNewPass(), user.getPassword())){
throw new BadRequestException("新密码不能与旧密码相同");
}
userService.updatePass(userDetails.getUsername(),EncryptUtils.encryptPassword(user.getNewPass()));
userService.updatePass(user.getUsername(),passwordEncoder.encode(passVo.getNewPass()));
return new ResponseEntity(HttpStatus.OK);
}
......@@ -158,13 +172,13 @@ public class UserController {
@ApiOperation("修改邮箱")
@PostMapping(value = "/updateEmail/{code}")
public ResponseEntity updateEmail(@PathVariable String code,@RequestBody User user){
UserDetails userDetails = SecurityUtils.getUserDetails();
if(!userDetails.getPassword().equals(EncryptUtils.encryptPassword(user.getPassword()))){
UserDto userDto = userService.findByName(SecurityUtils.getUsername());
if(!passwordEncoder.matches(user.getPassword(), userDto.getPassword())){
throw new BadRequestException("密码错误");
}
VerificationCode verificationCode = new VerificationCode(code, ElAdminConstant.RESET_MAIL,"email",user.getEmail());
verificationCodeService.validated(verificationCode);
userService.updateEmail(userDetails.getUsername(),user.getEmail());
userService.updateEmail(userDto.getUsername(),user.getEmail());
return new ResponseEntity(HttpStatus.OK);
}
......@@ -173,7 +187,8 @@ public class UserController {
* @param resources /
*/
private void checkLevel(User resources) {
Integer currentLevel = Collections.min(roleService.findByUsersId(SecurityUtils.getUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
UserDto user = userService.findByName(SecurityUtils.getUsername());
Integer currentLevel = Collections.min(roleService.findByUsersId(user.getId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
Integer optLevel = roleService.findByRoles(resources.getRoles());
if (currentLevel > optLevel) {
throw new BadRequestException("角色权限不足");
......
......@@ -4,10 +4,14 @@ import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.modules.system.service.dto.RoleDto;
import me.zhengjie.modules.system.service.dto.RoleQueryCriteria;
import me.zhengjie.modules.system.service.dto.RoleSmallDto;
import me.zhengjie.modules.system.service.dto.UserDto;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.GrantedAuthority;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Set;
......@@ -99,4 +103,11 @@ public interface RoleService {
* @throws IOException /
*/
void download(List<RoleDto> queryAll, HttpServletResponse response) throws IOException;
/**
* 获取用户权限信息
* @param user 用户信息
* @return 权限信息
*/
Collection<GrantedAuthority> mapToGrantedAuthorities(UserDto user);
}
......@@ -90,4 +90,10 @@ public interface UserService {
* @throws IOException /
*/
void download(List<UserDto> queryAll, HttpServletResponse response) throws IOException;
/**
* 用户自助修改资料
* @param resources /
*/
void updateCenter(User resources);
}
......@@ -20,6 +20,10 @@ public class UserDto implements Serializable {
private String username;
private String nickName;
private String sex;
private String avatar;
private String email;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment