Commit b822b4d2 by tangyi

Merge branch 'dev'

parents 8660b235 ec73b1e7
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
| 名称 | 版本 | | 名称 | 版本 |
| --------- | -------- | | --------- | -------- |
| `Spring Boot` | `2.1.8.RELEASE` | | `Spring Boot` | `2.1.9.RELEASE` |
| `Spring Cloud` | `Greenwich.SR3` | | `Spring Cloud` | `Greenwich.SR3` |
# 5 系统架构 # 5 系统架构
......
...@@ -35,5 +35,11 @@ ...@@ -35,5 +35,11 @@
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>${commons-io.version}</version> <version>${commons-io.version}</version>
</dependency> </dependency>
<!-- jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>
package com.github.tangyi.common.security.annotations;
import org.springframework.security.access.prepost.PreAuthorize;
import java.lang.annotation.*;
/**
* 超级管理员权限注解
*
* @author tangyi
* @date 2019/11/02 12:33
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@PreAuthorize("hasRole(T(com.github.tangyi.common.security.enums.Roles).ROLE_ADMIN)")
public @interface AdminAuthorization {
}
package com.github.tangyi.common.security.annotations;
import org.springframework.security.access.prepost.PreAuthorize;
import java.lang.annotation.*;
/**
* 租户或超管权限
*
* @author tangyi
* @date 2019/11/02 12:40
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@PreAuthorize("hasRole(T(com.github.tangyi.common.security.enums.Roles).ROLE_ADMIN) or hasRole(T(com.github.tangyi.common.security.enums.Roles).ROLE_TENANT_ADMIN) or hasRole(T(com.github.tangyi.common.security.enums.Roles).ROLE_TEACHER)")
public @interface AdminTenantTeacherAuthorization {
}
package com.github.tangyi.common.security.annotations;
import org.springframework.security.access.prepost.PreAuthorize;
import java.lang.annotation.*;
/**
* 普通用户权限
*
* @author tangyi
* @date 2019/11/02 12:44
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@PreAuthorize("hasRole(T(com.github.tangyi.common.security.enums.Roles).ROLE_USER)")
public @interface UserAuthorization {
}
...@@ -7,16 +7,6 @@ package com.github.tangyi.common.security.constant; ...@@ -7,16 +7,6 @@ package com.github.tangyi.common.security.constant;
public class SecurityConstant { public class SecurityConstant {
/** /**
* 基础角色
*/
public static final String BASE_ROLE = "role_user";
/**
* 超级管理员角色
*/
public static final String ROLE_ADMIN = "role_admin";
/**
* 租户管理员角色 * 租户管理员角色
*/ */
public static final String ROLE_TENANT_ADMIN = "role_tenant_admin"; public static final String ROLE_TENANT_ADMIN = "role_tenant_admin";
...@@ -37,11 +27,6 @@ public class SecurityConstant { ...@@ -37,11 +27,6 @@ public class SecurityConstant {
public static final String NORMAL = "0"; public static final String NORMAL = "0";
/** /**
* 异常状态
*/
public static final String ABNORMAL = "1";
/**
* 手机登录URL * 手机登录URL
*/ */
public static final String MOBILE_TOKEN_URL = "/mobile/token"; public static final String MOBILE_TOKEN_URL = "/mobile/token";
......
...@@ -15,36 +15,36 @@ public interface CustomUserDetailsService { ...@@ -15,36 +15,36 @@ public interface CustomUserDetailsService {
/** /**
* 根据用户名和租户标识查询 * 根据用户名和租户标识查询
* *
* @param tenantCode tenantCode
* @param username username * @param username username
* @param tenantCode tenantCode
* @return UserDetails * @return UserDetails
* @author tangyi * @author tangyi
* @date 2019/05/28 21:06 * @date 2019/05/28 21:06
*/ */
UserDetails loadUserByIdentifierAndTenantCode(String username, String tenantCode) throws UsernameNotFoundException; UserDetails loadUserByIdentifierAndTenantCode(String tenantCode, String username) throws UsernameNotFoundException;
/** /**
* 根据社交账号和租户标识查询 * 根据社交账号和租户标识查询
* *
* @param social social
* @param tenantCode tenantCode * @param tenantCode tenantCode
* @param mobileUser mobileUser * @param social social
* @param mobileUser mobileUser
* @return UserDetails * @return UserDetails
* @author tangyi * @author tangyi
* @date 2019/06/22 21:08 * @date 2019/06/22 21:08
*/ */
UserDetails loadUserBySocialAndTenantCode(String social, String tenantCode, MobileUser mobileUser) throws UsernameNotFoundException; UserDetails loadUserBySocialAndTenantCode(String tenantCode, String social, MobileUser mobileUser) throws UsernameNotFoundException;
/** /**
* 根据微信openId和租户标识查询 * 根据微信openId和租户标识查询
* *
* @param tenantCode tenantCode
* @param code code * @param code code
* @param tenantCode tenantCode
* @param wxUser wxUser * @param wxUser wxUser
* @return UserDetails * @return UserDetails
* @author tangyi * @author tangyi
* @date 2019/07/05 20:04:59 * @date 2019/07/05 20:04:59
*/ */
UserDetails loadUserByWxCodeAndTenantCode(String code, String tenantCode, WxUser wxUser) throws UsernameNotFoundException; UserDetails loadUserByWxCodeAndTenantCode(String tenantCode, String code, WxUser wxUser) throws UsernameNotFoundException;
} }
package com.github.tangyi.common.security.enums;
import org.springframework.security.core.GrantedAuthority;
/**
* 角色枚举
*
* @author tangyi
* @date 2019/11/02 12:30
*/
public enum Roles implements GrantedAuthority {
/**
* 普通用户
*/
ROLE_USER,
/**
* 超级管理员
*/
ROLE_ADMIN,
/**
* 租户管理员
*/
ROLE_TENANT_ADMIN,
/**
* 老师
*/
ROLE_TEACHER;
@Override
public String getAuthority() {
return name();
}
}
package com.github.tangyi.common.security.event;
import lombok.Data;
import org.springframework.context.ApplicationEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
/**
*
* 登录失败事件
*
* @author tangyi
* @date 2019-11-11 23:46
*/
@Data
public class CustomAuthenticationFailureEvent extends ApplicationEvent {
private UserDetails userDetails;
public CustomAuthenticationFailureEvent(Authentication authentication, UserDetails userDetails) {
super(authentication);
this.userDetails = userDetails;
}
}
package com.github.tangyi.common.security.event;
import lombok.Data;
import org.springframework.context.ApplicationEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
/**
* 登录成功事件
*
* @author tangyi
* @date 2019-11-11 23:40
*/
@Data
public class CustomAuthenticationSuccessEvent extends ApplicationEvent {
private UserDetails userDetails;
public CustomAuthenticationSuccessEvent(Authentication authentication, UserDetails userDetails) {
super(authentication);
this.userDetails = userDetails;
}
}
package com.github.tangyi.common.security.exceptions;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.github.tangyi.common.security.serializer.CustomOauthExceptionSerializer;
import lombok.Data;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
/**
* 定制OAuth2Exception
*
* @author tangyi
* @date 2019/3/18 22:36
*/
@Data
@JsonSerialize(using = CustomOauthExceptionSerializer.class)
public class CustomOauthException extends OAuth2Exception {
/**
* 错误码
*/
private int code;
public CustomOauthException(String msg, int code) {
super(msg);
this.code = code;
}
}
package com.github.tangyi.common.security.mobile; package com.github.tangyi.common.security.mobile;
import com.github.tangyi.common.security.core.CustomUserDetailsService; import com.github.tangyi.common.security.core.CustomUserDetailsService;
import com.github.tangyi.common.security.event.CustomAuthenticationFailureEvent;
import com.github.tangyi.common.security.event.CustomAuthenticationSuccessEvent;
import com.github.tangyi.common.security.tenant.TenantContextHolder; import com.github.tangyi.common.security.tenant.TenantContextHolder;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.support.MessageSourceAccessor; import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
...@@ -24,18 +27,22 @@ public class MobileAuthenticationProvider implements AuthenticationProvider { ...@@ -24,18 +27,22 @@ public class MobileAuthenticationProvider implements AuthenticationProvider {
private CustomUserDetailsService customUserDetailsService; private CustomUserDetailsService customUserDetailsService;
@Override private ApplicationEventPublisher publisher;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException { public Authentication authenticate(Authentication authentication) throws AuthenticationException {
MobileAuthenticationToken mobileAuthenticationToken = (MobileAuthenticationToken) authentication; MobileAuthenticationToken mobileAuthenticationToken = (MobileAuthenticationToken) authentication;
String principal = mobileAuthenticationToken.getPrincipal().toString(); String principal = mobileAuthenticationToken.getPrincipal().toString();
UserDetails userDetails = customUserDetailsService.loadUserBySocialAndTenantCode(principal, TenantContextHolder.getTenantCode(), mobileAuthenticationToken.getMobileUser()); UserDetails userDetails = customUserDetailsService.loadUserBySocialAndTenantCode(TenantContextHolder.getTenantCode(), principal, mobileAuthenticationToken.getMobileUser());
if (userDetails == null) { if (userDetails == null) {
log.debug("Authentication failed: no credentials provided"); log.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.noopBindAccount", "Noop Bind Account")); publisher.publishEvent(new CustomAuthenticationFailureEvent(authentication, userDetails));
throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.noopBindAccount", "Noop Bind Account"));
} }
MobileAuthenticationToken authenticationToken = new MobileAuthenticationToken(userDetails, userDetails.getAuthorities()); MobileAuthenticationToken authenticationToken = new MobileAuthenticationToken(userDetails, userDetails.getAuthorities());
authenticationToken.setDetails(mobileAuthenticationToken.getDetails()); authenticationToken.setDetails(mobileAuthenticationToken.getDetails());
return authenticationToken; publisher.publishEvent(new CustomAuthenticationSuccessEvent(authentication, userDetails));
return authenticationToken;
} }
@Override @Override
......
...@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; ...@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tangyi.common.security.core.CustomUserDetailsService; import com.github.tangyi.common.security.core.CustomUserDetailsService;
import lombok.Data; import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.authentication.AuthenticationEventPublisher; import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
...@@ -27,6 +28,9 @@ public class MobileSecurityConfigurer extends SecurityConfigurerAdapter<DefaultS ...@@ -27,6 +28,9 @@ public class MobileSecurityConfigurer extends SecurityConfigurerAdapter<DefaultS
@Autowired @Autowired
private AuthenticationEventPublisher defaultAuthenticationEventPublisher; private AuthenticationEventPublisher defaultAuthenticationEventPublisher;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
private AuthenticationSuccessHandler mobileLoginSuccessHandler; private AuthenticationSuccessHandler mobileLoginSuccessHandler;
private CustomUserDetailsService userDetailsService; private CustomUserDetailsService userDetailsService;
...@@ -40,6 +44,7 @@ public class MobileSecurityConfigurer extends SecurityConfigurerAdapter<DefaultS ...@@ -40,6 +44,7 @@ public class MobileSecurityConfigurer extends SecurityConfigurerAdapter<DefaultS
mobileAuthenticationFilter.setEventPublisher(defaultAuthenticationEventPublisher); mobileAuthenticationFilter.setEventPublisher(defaultAuthenticationEventPublisher);
MobileAuthenticationProvider mobileAuthenticationProvider = new MobileAuthenticationProvider(); MobileAuthenticationProvider mobileAuthenticationProvider = new MobileAuthenticationProvider();
mobileAuthenticationProvider.setCustomUserDetailsService(userDetailsService); mobileAuthenticationProvider.setCustomUserDetailsService(userDetailsService);
mobileAuthenticationProvider.setPublisher(applicationEventPublisher);
// 增加手机登录的过滤器 // 增加手机登录的过滤器
http.authenticationProvider(mobileAuthenticationProvider).addFilterAfter(mobileAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); http.authenticationProvider(mobileAuthenticationProvider).addFilterAfter(mobileAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
} }
......
package com.github.tangyi.common.security.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.github.tangyi.common.security.exceptions.CustomOauthException;
import java.io.IOException;
import java.util.Map;
/**
* 定制OauthException序列化
*
* @author tangyi
* @date 2019/3/18 22:37
*/
public class CustomOauthExceptionSerializer extends StdSerializer<CustomOauthException> {
public CustomOauthExceptionSerializer() {
super(CustomOauthException.class);
}
@Override
public void serialize(CustomOauthException value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
// 封装属性,和ResponseBean对应
gen.writeNumberField("status", value.getCode());
// 返回给前端的code
gen.writeNumberField("code", value.getCode());
// 提示信息
gen.writeStringField("msg", value.getMessage());
if (value.getAdditionalInformation() != null) {
for (Map.Entry<String, String> entry : value.getAdditionalInformation().entrySet()) {
String key = entry.getKey();
String add = entry.getValue();
gen.writeStringField(key, add);
}
}
gen.writeEndObject();
}
}
package com.github.tangyi.common.security.wx; package com.github.tangyi.common.security.wx;
import com.github.tangyi.common.security.core.CustomUserDetailsService; import com.github.tangyi.common.security.core.CustomUserDetailsService;
import com.github.tangyi.common.security.event.CustomAuthenticationFailureEvent;
import com.github.tangyi.common.security.event.CustomAuthenticationSuccessEvent;
import com.github.tangyi.common.security.tenant.TenantContextHolder; import com.github.tangyi.common.security.tenant.TenantContextHolder;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.support.MessageSourceAccessor; import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
...@@ -24,6 +27,8 @@ public class WxAuthenticationProvider implements AuthenticationProvider { ...@@ -24,6 +27,8 @@ public class WxAuthenticationProvider implements AuthenticationProvider {
private CustomUserDetailsService customUserDetailsService; private CustomUserDetailsService customUserDetailsService;
private ApplicationEventPublisher publisher;
@Override @Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException { public Authentication authenticate(Authentication authentication) throws AuthenticationException {
WxAuthenticationToken wxAuthenticationToken = (WxAuthenticationToken) authentication; WxAuthenticationToken wxAuthenticationToken = (WxAuthenticationToken) authentication;
...@@ -32,11 +37,13 @@ public class WxAuthenticationProvider implements AuthenticationProvider { ...@@ -32,11 +37,13 @@ public class WxAuthenticationProvider implements AuthenticationProvider {
UserDetails userDetails = customUserDetailsService.loadUserByWxCodeAndTenantCode(principal, TenantContextHolder.getTenantCode(), wxAuthenticationToken.getWxUser()); UserDetails userDetails = customUserDetailsService.loadUserByWxCodeAndTenantCode(principal, TenantContextHolder.getTenantCode(), wxAuthenticationToken.getWxUser());
if (userDetails == null) { if (userDetails == null) {
log.debug("Authentication failed: no credentials provided"); log.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.noopBindAccount", "Noop Bind Account")); publisher.publishEvent(new CustomAuthenticationFailureEvent(authentication, userDetails));
throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.noopBindAccount", "Noop Bind Account"));
} }
WxAuthenticationToken authenticationToken = new WxAuthenticationToken(userDetails, userDetails.getAuthorities()); WxAuthenticationToken authenticationToken = new WxAuthenticationToken(userDetails, userDetails.getAuthorities());
authenticationToken.setDetails(wxAuthenticationToken.getDetails()); authenticationToken.setDetails(wxAuthenticationToken.getDetails());
return authenticationToken; publisher.publishEvent(new CustomAuthenticationSuccessEvent(authentication, userDetails));
return authenticationToken;
} }
@Override @Override
......
...@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; ...@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tangyi.common.security.core.CustomUserDetailsService; import com.github.tangyi.common.security.core.CustomUserDetailsService;
import lombok.Data; import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.authentication.AuthenticationEventPublisher; import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
...@@ -27,6 +28,9 @@ public class WxSecurityConfigurer extends SecurityConfigurerAdapter<DefaultSecur ...@@ -27,6 +28,9 @@ public class WxSecurityConfigurer extends SecurityConfigurerAdapter<DefaultSecur
@Autowired @Autowired
private AuthenticationEventPublisher defaultAuthenticationEventPublisher; private AuthenticationEventPublisher defaultAuthenticationEventPublisher;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
private AuthenticationSuccessHandler wxLoginSuccessHandler; private AuthenticationSuccessHandler wxLoginSuccessHandler;
private CustomUserDetailsService userDetailsService; private CustomUserDetailsService userDetailsService;
...@@ -40,6 +44,7 @@ public class WxSecurityConfigurer extends SecurityConfigurerAdapter<DefaultSecur ...@@ -40,6 +44,7 @@ public class WxSecurityConfigurer extends SecurityConfigurerAdapter<DefaultSecur
wxAuthenticationFilter.setEventPublisher(defaultAuthenticationEventPublisher); wxAuthenticationFilter.setEventPublisher(defaultAuthenticationEventPublisher);
WxAuthenticationProvider wxAuthenticationProvider = new WxAuthenticationProvider(); WxAuthenticationProvider wxAuthenticationProvider = new WxAuthenticationProvider();
wxAuthenticationProvider.setCustomUserDetailsService(userDetailsService); wxAuthenticationProvider.setCustomUserDetailsService(userDetailsService);
wxAuthenticationProvider.setPublisher(applicationEventPublisher);
// 增加微信登录的过滤器 // 增加微信登录的过滤器
http.authenticationProvider(wxAuthenticationProvider).addFilterAfter(wxAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); http.authenticationProvider(wxAuthenticationProvider).addFilterAfter(wxAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
package com.github.tangyi.auth.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
*
* 配置aop
*
* @author tangyi
* @date 2019-11-12 20:13
*/
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
}
package com.github.tangyi.auth.config; package com.github.tangyi.auth.config;
import com.github.tangyi.auth.filter.CustomTokenEndpointAuthenticationFilter;
import com.github.tangyi.auth.security.CustomTokenConverter; import com.github.tangyi.auth.security.CustomTokenConverter;
import com.github.tangyi.common.security.core.ClientDetailsServiceImpl; import com.github.tangyi.common.security.core.ClientDetailsServiceImpl;
import com.github.tangyi.common.security.exceptions.CustomOauthException;
import com.github.tangyi.user.api.feign.UserServiceClient;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.bootstrap.encrypt.KeyProperties; import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory; import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
...@@ -37,11 +30,6 @@ import javax.sql.DataSource; ...@@ -37,11 +30,6 @@ import javax.sql.DataSource;
public class CustomAuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter { public class CustomAuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {
/** /**
* 认证管理器
*/
private final AuthenticationManager authenticationManager;
/**
* redis连接工厂 * redis连接工厂
*/ */
private final RedisConnectionFactory redisConnectionFactory; private final RedisConnectionFactory redisConnectionFactory;
...@@ -56,21 +44,13 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf ...@@ -56,21 +44,13 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
*/ */
private final KeyProperties keyProperties; private final KeyProperties keyProperties;
private final UserServiceClient userServiceClient;
private OAuth2RequestFactory oAuth2RequestFactory;
@Autowired @Autowired
public CustomAuthorizationServerConfigurer(AuthenticationManager authenticationManager, public CustomAuthorizationServerConfigurer(RedisConnectionFactory redisConnectionFactory,
RedisConnectionFactory redisConnectionFactory, DataSource dataSource,
DataSource dataSource, KeyProperties keyProperties) {
KeyProperties keyProperties,
UserServiceClient userServiceClient) {
this.authenticationManager = authenticationManager;
this.redisConnectionFactory = redisConnectionFactory; this.redisConnectionFactory = redisConnectionFactory;
this.dataSource = dataSource; this.dataSource = dataSource;
this.keyProperties = keyProperties; this.keyProperties = keyProperties;
this.userServiceClient = userServiceClient;
} }
/** /**
...@@ -123,25 +103,11 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf ...@@ -123,25 +103,11 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
*/ */
@Override @Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) { public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
oAuth2RequestFactory = endpoints.getOAuth2RequestFactory(); endpoints
endpoints
// 将token存储到redis // 将token存储到redis
.tokenStore(tokenStore()) .tokenStore(tokenStore())
// token增强 // token增强
.tokenEnhancer(jwtTokenEnhancer()) .tokenEnhancer(jwtTokenEnhancer());
// 认证管理器
.authenticationManager(authenticationManager)
// 异常处理
.exceptionTranslator(e -> {
if (e instanceof OAuth2Exception) {
OAuth2Exception oAuth2Exception = (OAuth2Exception) e;
return ResponseEntity
.status(oAuth2Exception.getHttpErrorCode())
.body(new CustomOauthException(oAuth2Exception.getMessage(), oAuth2Exception.getHttpErrorCode()));
} else {
throw e;
}
});
} }
/** /**
...@@ -158,7 +124,6 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf ...@@ -158,7 +124,6 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
// 开启/oauth/check_token验证端口认证权限访问 // 开启/oauth/check_token验证端口认证权限访问
.checkTokenAccess("isAuthenticated()") .checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients(); .allowFormAuthenticationForClients();
//.addTokenEndpointAuthenticationFilter(new CustomTokenEndpointAuthenticationFilter(authenticationManager, oAuth2RequestFactory, userServiceClient));
} }
} }
package com.github.tangyi.auth.config; package com.github.tangyi.auth.config;
import com.github.tangyi.auth.error.CustomOAuth2AccessDeniedHandler;
import com.github.tangyi.auth.security.CustomUserDetailsAuthenticationProvider; import com.github.tangyi.auth.security.CustomUserDetailsAuthenticationProvider;
import com.github.tangyi.common.security.core.CustomUserDetailsService; import com.github.tangyi.common.security.core.CustomUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
...@@ -12,7 +14,10 @@ import org.springframework.security.config.annotation.method.configuration.Enabl ...@@ -12,7 +14,10 @@ import org.springframework.security.config.annotation.method.configuration.Enabl
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration;
import org.springframework.security.web.access.AccessDeniedHandler;
/** /**
* Spring Security配置 * Spring Security配置
...@@ -28,6 +33,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { ...@@ -28,6 +33,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
private CustomUserDetailsService userDetailsService; private CustomUserDetailsService userDetailsService;
@Autowired
private AuthorizationServerEndpointsConfiguration endpoints;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http http
...@@ -35,6 +46,16 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { ...@@ -35,6 +46,16 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.csrf().disable() .csrf().disable()
.authorizeRequests() .authorizeRequests()
.anyRequest().authenticated(); .anyRequest().authenticated();
if (!endpoints.getEndpointsConfigurer().isUserDetailsServiceOverride()) {
UserDetailsService userDetailsService = http.getSharedObject(UserDetailsService.class);
endpoints.getEndpointsConfigurer().userDetailsService(userDetailsService);
}
// 认证管理器
endpoints.getEndpointsConfigurer().authenticationManager(authenticationManager());
// accessDeniedHandler
http.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler());
} }
@Bean @Bean
...@@ -54,7 +75,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { ...@@ -54,7 +75,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
*/ */
@Bean @Bean
public AuthenticationProvider authProvider() { public AuthenticationProvider authProvider() {
return new CustomUserDetailsAuthenticationProvider(encoder(), userDetailsService); return new CustomUserDetailsAuthenticationProvider(encoder(), userDetailsService, applicationEventPublisher);
} }
@Override @Override
...@@ -62,5 +83,10 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { ...@@ -62,5 +83,10 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected AuthenticationManager authenticationManager() throws Exception { protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager(); return super.authenticationManager();
} }
@Bean
public AccessDeniedHandler accessDeniedHandler() {
return new CustomOAuth2AccessDeniedHandler();
}
} }
...@@ -9,7 +9,7 @@ import com.github.tangyi.common.core.utils.PageUtil; ...@@ -9,7 +9,7 @@ import com.github.tangyi.common.core.utils.PageUtil;
import com.github.tangyi.common.core.utils.SysUtil; import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.annotations.AdminAuthorization;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiImplicitParams;
...@@ -17,7 +17,6 @@ import io.swagger.annotations.ApiOperation; ...@@ -17,7 +17,6 @@ import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
...@@ -113,7 +112,7 @@ public class OauthClientDetailsController extends BaseController { ...@@ -113,7 +112,7 @@ public class OauthClientDetailsController extends BaseController {
* @date 2019/03/30 16:57 * @date 2019/03/30 16:57
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('sys:client:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminAuthorization
@ApiOperation(value = "创建客户端", notes = "创建客户端") @ApiOperation(value = "创建客户端", notes = "创建客户端")
@ApiImplicitParam(name = "oauthClientDetails", value = "客户端实体oauthClientDetails", required = true, dataType = "OauthClientDetails") @ApiImplicitParam(name = "oauthClientDetails", value = "客户端实体oauthClientDetails", required = true, dataType = "OauthClientDetails")
@Log("新增客户端") @Log("新增客户端")
...@@ -133,7 +132,7 @@ public class OauthClientDetailsController extends BaseController { ...@@ -133,7 +132,7 @@ public class OauthClientDetailsController extends BaseController {
* @date 2019/03/30 16:56 * @date 2019/03/30 16:56
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('sys:client:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminAuthorization
@ApiOperation(value = "更新客户端信息", notes = "根据客户端id更新客户端的基本信息") @ApiOperation(value = "更新客户端信息", notes = "根据客户端id更新客户端的基本信息")
@ApiImplicitParam(name = "oauthClientDetails", value = "客户端实体oauthClientDetails", required = true, dataType = "OauthClientDetails") @ApiImplicitParam(name = "oauthClientDetails", value = "客户端实体oauthClientDetails", required = true, dataType = "OauthClientDetails")
@Log("修改客户端") @Log("修改客户端")
...@@ -155,7 +154,7 @@ public class OauthClientDetailsController extends BaseController { ...@@ -155,7 +154,7 @@ public class OauthClientDetailsController extends BaseController {
* @date 2019/03/30 16:59 * @date 2019/03/30 16:59
*/ */
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
@PreAuthorize("hasAuthority('sys:client:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminAuthorization
@ApiOperation(value = "删除客户端", notes = "根据ID删除客户端") @ApiOperation(value = "删除客户端", notes = "根据ID删除客户端")
@ApiImplicitParam(name = "id", value = "客户端ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "客户端ID", required = true, paramType = "path")
@Log("删除客户端") @Log("删除客户端")
...@@ -176,7 +175,7 @@ public class OauthClientDetailsController extends BaseController { ...@@ -176,7 +175,7 @@ public class OauthClientDetailsController extends BaseController {
* @date 2019/03/30 17:01 * @date 2019/03/30 17:01
*/ */
@PostMapping("deleteAll") @PostMapping("deleteAll")
@PreAuthorize("hasAuthority('sys:client:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminAuthorization
@ApiOperation(value = "批量删除客户端", notes = "根据客户端id批量删除客户端") @ApiOperation(value = "批量删除客户端", notes = "根据客户端id批量删除客户端")
@ApiImplicitParam(name = "oauthClientDetails", value = "客户端信息", dataType = "OauthClientDetails") @ApiImplicitParam(name = "oauthClientDetails", value = "客户端信息", dataType = "OauthClientDetails")
@Log("批量删除客户端") @Log("批量删除客户端")
......
package com.github.tangyi.auth.error;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.oauth2.provider.error.AbstractOAuth2SecurityExceptionHandler;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.web.context.request.ServletWebRequest;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
*
* accessDeniedHandler,return ResponseBean
*
* @author tangyi
* @date 2019-11-11 21:24
*/
@Slf4j
public class CustomOAuth2AccessDeniedHandler extends AbstractOAuth2SecurityExceptionHandler
implements AccessDeniedHandler {
private WebResponseExceptionTranslator<?> exceptionTranslator = new DefaultWebResponseExceptionTranslator();
private CustomOAuth2ExceptionRenderer exceptionRenderer = new CustomOAuth2ExceptionRenderer();
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException authException)
throws IOException {
try {
ResponseEntity<?> result = exceptionTranslator.translate(authException);
result = enhanceResponse(result, authException);
exceptionRenderer.handleResponseBeanResponse(result, new ServletWebRequest(request, response));
response.flushBuffer();
} catch (ServletException e) {
log.error(e.getMessage(), e);
} catch (IOException | RuntimeException e) {
throw e;
} catch (Exception e) {
// Wrap other Exceptions. These are not expected to happen
throw new RuntimeException(e);
}
}
}
package com.github.tangyi.auth.error;
import com.github.tangyi.common.core.model.ResponseBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.oauth2.http.converter.jaxb.JaxbOAuth2ExceptionMessageConverter;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
*
* render异常
*
* @author tangyi
* @date 2019-11-11 21:29
*/
@Slf4j
public class CustomOAuth2ExceptionRenderer {
private List<HttpMessageConverter<?>> messageConverters = geDefaultMessageConverters();
public void handleResponseBeanResponse(ResponseEntity<?> responseEntity, ServletWebRequest webRequest)
throws Exception {
if (responseEntity == null) {
return;
}
HttpInputMessage inputMessage = createHttpInputMessage(webRequest);
HttpOutputMessage outputMessage = createHttpOutputMessage(webRequest);
if (outputMessage instanceof ServerHttpResponse) {
((ServerHttpResponse) outputMessage).setStatusCode(responseEntity.getStatusCode());
}
HttpHeaders entityHeaders = responseEntity.getHeaders();
if (!entityHeaders.isEmpty()) {
outputMessage.getHeaders().putAll(entityHeaders);
}
Object body = responseEntity.getBody();
if (body != null) {
// 返回ResponseBean
ResponseBean<?> responseBean = new ResponseBean<>(body);
responseBean.setStatus(responseEntity.getStatusCode().value());
writeWithMessageConverters(responseBean, inputMessage, outputMessage);
} else {
// flush headers
outputMessage.getBody();
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void writeWithMessageConverters(Object returnValue, HttpInputMessage inputMessage,
HttpOutputMessage outputMessage) throws IOException, HttpMediaTypeNotAcceptableException {
List<MediaType> acceptedMediaTypes = inputMessage.getHeaders().getAccept();
if (acceptedMediaTypes.isEmpty()) {
acceptedMediaTypes = Collections.singletonList(MediaType.ALL);
}
MediaType.sortByQualityValue(acceptedMediaTypes);
Class<?> returnValueType = returnValue.getClass();
List<MediaType> allSupportedMediaTypes = new ArrayList<>();
for (MediaType acceptedMediaType : acceptedMediaTypes) {
for (HttpMessageConverter messageConverter : messageConverters) {
if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {
messageConverter.write(returnValue, acceptedMediaType, outputMessage);
if (log.isDebugEnabled()) {
MediaType contentType = outputMessage.getHeaders().getContentType();
if (contentType == null) {
contentType = acceptedMediaType;
}
log.debug("Written [" + returnValue + "] as \"" + contentType + "\" using [" + messageConverter
+ "]");
}
return;
}
}
}
for (HttpMessageConverter messageConverter : messageConverters) {
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
}
throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);
}
private List<HttpMessageConverter<?>> geDefaultMessageConverters() {
List<HttpMessageConverter<?>> result = new ArrayList<>(new RestTemplate().getMessageConverters());
result.add(new JaxbOAuth2ExceptionMessageConverter());
return result;
}
private HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest) {
return new ServletServerHttpRequest(webRequest.getNativeRequest(HttpServletRequest.class));
}
private HttpOutputMessage createHttpOutputMessage(NativeWebRequest webRequest) {
return new ServletServerHttpResponse((HttpServletResponse) webRequest.getNativeResponse());
}
}
package com.github.tangyi.auth.filter;
import com.github.tangyi.auth.model.CustomUserDetails;
import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.constant.ServiceConstant;
import com.github.tangyi.common.core.model.Log;
import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.user.api.feign.UserServiceClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
import org.springframework.security.oauth2.provider.endpoint.TokenEndpointAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
*
* 登录成功后的处理,如记录登录日志
*
* @author tangyi
* @date 2019-10-11 12:08
*/
@Slf4j
public class CustomTokenEndpointAuthenticationFilter extends TokenEndpointAuthenticationFilter {
private UserServiceClient userServiceClient;
public CustomTokenEndpointAuthenticationFilter(AuthenticationManager authenticationManager,
OAuth2RequestFactory oAuth2RequestFactory, UserServiceClient userServiceClient) {
super(authenticationManager, oAuth2RequestFactory);
this.userServiceClient = userServiceClient;
}
@Override
protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException {
// 登录成功后的处理
log.info("CustomTokenEndpointAuthenticationFilter onSuccessfulAuthentication");
CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
String tenantCode = userDetails.getTenantCode();
String username = userDetails.getUsername();
log.info("CustomTokenEndpointAuthenticationFilter 登录成功, tenantCode: {}, username: {}", tenantCode, username);
// 记录日志
Log logInfo = new Log();
logInfo.setCommonValue(username, SysUtil.getSysCode(), tenantCode);
logInfo.setTitle("用户登录");
logInfo.setType(CommonConstant.STATUS_NORMAL);
logInfo.setMethod(request.getMethod());
logInfo.setTime(String.valueOf(System.currentTimeMillis() - userDetails.getStart()));
logInfo.setRequestUri(request.getRequestURI());
// 获取ip、浏览器信息
logInfo.setIp(request.getRemoteAddr());
logInfo.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
logInfo.setServiceId(ServiceConstant.AUTH_SERVICE);
// 记录日志
saveLoginSuccessLog(logInfo);
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
// 认证前的特殊处理
// if (!condition) {
// throw new AuthenticationServiceException("condition not satisfied");
// }
log.info("CustomTokenEndpointAuthenticationFilter doFilter");
super.doFilter(req, res, chain);
}
/**
* 异步记录登录日志
*
* @author tangyi
* @date 2019/05/30 23:30
*/
@Async
public void saveLoginSuccessLog(Log logInfo) {
try {
userServiceClient.saveLog(logInfo);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
package com.github.tangyi.auth.listener;
import com.github.tangyi.common.security.event.CustomAuthenticationFailureEvent;
import com.github.tangyi.user.api.feign.UserServiceClient;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
*
* 处理登录失败事件
*
* @author tangyi
* @date 2019-11-11 23:52
*/
@Slf4j
@AllArgsConstructor
@Component
public class LoginFailureListener implements ApplicationListener<CustomAuthenticationFailureEvent> {
private final UserServiceClient userServiceClient;
@Override
public void onApplicationEvent(CustomAuthenticationFailureEvent event) {
// 登录失败后的处理
}
}
package com.github.tangyi.auth.listener;
import com.github.tangyi.auth.model.CustomUserDetails;
import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.constant.ServiceConstant;
import com.github.tangyi.common.core.model.Log;
import com.github.tangyi.common.core.utils.DateUtils;
import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.security.event.CustomAuthenticationSuccessEvent;
import com.github.tangyi.user.api.dto.UserDto;
import com.github.tangyi.user.api.feign.UserServiceClient;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
/**
*
* 处理登录成功事件
*
* @author tangyi
* @date 2019-11-11 23:48
*/
@Slf4j
@AllArgsConstructor
@Component
public class LoginSuccessListener implements ApplicationListener<CustomAuthenticationSuccessEvent> {
private final UserServiceClient userServiceClient;
@Override
public void onApplicationEvent(CustomAuthenticationSuccessEvent event) {
// 登录成功后的处理
UserDetails userDetails = event.getUserDetails();
if (userDetails instanceof CustomUserDetails) {
CustomUserDetails customUserDetails = (CustomUserDetails) userDetails;
String tenantCode = customUserDetails.getTenantCode();
String username = userDetails.getUsername();
log.info("{} login success, tenantCode: {}", username, tenantCode);
// 记录日志
Log logInfo = new Log();
logInfo.setTitle("用户登录");
logInfo.setCommonValue(username, SysUtil.getSysCode(), tenantCode);
logInfo.setTime(String.valueOf(System.currentTimeMillis() - customUserDetails.getStart()));
logInfo.setType(CommonConstant.STATUS_NORMAL);
HttpServletRequest request = currentRequestAttributes().getRequest();
logInfo.setMethod(request.getMethod());
logInfo.setRequestUri(request.getRequestURI());
// 获取ip、浏览器信息
logInfo.setIp(request.getRemoteAddr());
logInfo.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
logInfo.setServiceId(ServiceConstant.AUTH_SERVICE);
// 记录日志和登录时间
UserDto userDto = new UserDto();
userDto.setIdentifier(username);
userDto.setLoginTime(DateUtils.asDate(LocalDateTime.now()));
saveLoginInfo(logInfo, userDto);
}
}
/**
* 异步记录登录日志
*
* @param logInfo logInfo
* @param userDto userDto
* @author tangyi
* @date 2019/05/30 23:30
*/
@Async
public void saveLoginInfo(Log logInfo, UserDto userDto) {
try {
userServiceClient.saveLog(logInfo);
//userServiceClient.updateUser(userDto);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
/**
*
* 获取当前request
*
* @return ServletRequestAttributes
* @author tangyi
* @date 2019-11-12 00:15
*/
private static ServletRequestAttributes currentRequestAttributes() {
RequestAttributes requestAttr = RequestContextHolder.currentRequestAttributes();
if (!(requestAttr instanceof ServletRequestAttributes)) {
throw new IllegalStateException("Current request is not a servlet request");
}
return (ServletRequestAttributes) requestAttr;
}
}
package com.github.tangyi.auth.security; package com.github.tangyi.auth.security;
import com.github.tangyi.common.security.event.CustomAuthenticationFailureEvent;
import com.github.tangyi.common.security.event.CustomAuthenticationSuccessEvent;
import com.github.tangyi.common.core.exceptions.TenantNotFoundException; import com.github.tangyi.common.core.exceptions.TenantNotFoundException;
import com.github.tangyi.common.security.core.CustomUserDetailsService; import com.github.tangyi.common.security.core.CustomUserDetailsService;
import com.github.tangyi.common.security.tenant.TenantContextHolder; import com.github.tangyi.common.security.tenant.TenantContextHolder;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException; import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
...@@ -30,9 +33,12 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails ...@@ -30,9 +33,12 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails
private String userNotFoundEncodedPassword; private String userNotFoundEncodedPassword;
public CustomUserDetailsAuthenticationProvider(PasswordEncoder passwordEncoder, CustomUserDetailsService userDetailsService) { private ApplicationEventPublisher publisher;
public CustomUserDetailsAuthenticationProvider(PasswordEncoder passwordEncoder, CustomUserDetailsService userDetailsService, ApplicationEventPublisher publisher) {
this.passwordEncoder = passwordEncoder; this.passwordEncoder = passwordEncoder;
this.userDetailsService = userDetailsService; this.userDetailsService = userDetailsService;
this.publisher = publisher;
} }
@Override @Override
...@@ -46,9 +52,11 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails ...@@ -46,9 +52,11 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails
// 匹配密码 // 匹配密码
if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) { if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
log.debug("认证失败: 密码错误."); log.debug("认证失败: 密码错误.");
throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "密码错误.")); publisher.publishEvent(new CustomAuthenticationFailureEvent(authentication, userDetails));
throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "密码错误."));
} }
} publisher.publishEvent(new CustomAuthenticationSuccessEvent(authentication, userDetails));
}
@Override @Override
protected void doAfterPropertiesSet() throws Exception { protected void doAfterPropertiesSet() throws Exception {
...@@ -70,9 +78,9 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails ...@@ -70,9 +78,9 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails
UserDetails loadedUser; UserDetails loadedUser;
try { try {
// 加载用户信息 // 加载用户信息
loadedUser = this.userDetailsService.loadUserByIdentifierAndTenantCode(authentication.getPrincipal().toString(), TenantContextHolder.getTenantCode()); loadedUser = this.userDetailsService.loadUserByIdentifierAndTenantCode(TenantContextHolder.getTenantCode(), authentication.getPrincipal().toString());
} catch (TenantNotFoundException tenantNotFound) { } catch (TenantNotFoundException tenantNotFound) {
throw tenantNotFound; throw new InternalAuthenticationServiceException(tenantNotFound.getMessage(), tenantNotFound);
} catch (UsernameNotFoundException notFound) { } catch (UsernameNotFoundException notFound) {
if (authentication.getCredentials() != null) { if (authentication.getCredentials() != null) {
String presentedPassword = authentication.getCredentials().toString(); String presentedPassword = authentication.getCredentials().toString();
......
...@@ -9,24 +9,18 @@ import com.github.tangyi.common.core.exceptions.CommonException; ...@@ -9,24 +9,18 @@ import com.github.tangyi.common.core.exceptions.CommonException;
import com.github.tangyi.common.core.exceptions.ServiceException; import com.github.tangyi.common.core.exceptions.ServiceException;
import com.github.tangyi.common.core.exceptions.TenantNotFoundException; import com.github.tangyi.common.core.exceptions.TenantNotFoundException;
import com.github.tangyi.common.core.model.ResponseBean; import com.github.tangyi.common.core.model.ResponseBean;
import com.github.tangyi.common.core.properties.SysProperties;
import com.github.tangyi.common.core.utils.DateUtils; import com.github.tangyi.common.core.utils.DateUtils;
import com.github.tangyi.common.core.utils.ResponseUtil; import com.github.tangyi.common.core.utils.ResponseUtil;
import com.github.tangyi.common.core.vo.RoleVo;
import com.github.tangyi.common.core.vo.UserVo; import com.github.tangyi.common.core.vo.UserVo;
import com.github.tangyi.common.security.core.CustomUserDetailsService; import com.github.tangyi.common.security.core.CustomUserDetailsService;
import com.github.tangyi.common.security.core.GrantedAuthorityImpl; import com.github.tangyi.common.security.core.GrantedAuthorityImpl;
import com.github.tangyi.common.security.mobile.MobileUser; import com.github.tangyi.common.security.mobile.MobileUser;
import com.github.tangyi.common.security.wx.WxUser; import com.github.tangyi.common.security.wx.WxUser;
import com.github.tangyi.user.api.constant.MenuConstant;
import com.github.tangyi.user.api.dto.UserDto; import com.github.tangyi.user.api.dto.UserDto;
import com.github.tangyi.user.api.enums.IdentityType; import com.github.tangyi.user.api.enums.IdentityType;
import com.github.tangyi.user.api.feign.UserServiceClient; import com.github.tangyi.user.api.feign.UserServiceClient;
import com.github.tangyi.user.api.module.Menu;
import com.github.tangyi.user.api.module.Tenant; import com.github.tangyi.user.api.module.Tenant;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
...@@ -35,8 +29,6 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException; ...@@ -35,8 +29,6 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -52,49 +44,46 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService { ...@@ -52,49 +44,46 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
private final UserServiceClient userServiceClient; private final UserServiceClient userServiceClient;
private final SysProperties sysProperties;
private final WxSessionService wxService; private final WxSessionService wxService;
/** /**
* 加载用户信息 * 加载用户信息
* *
* @param tenantCode 租户标识
* @param username 用户名 * @param username 用户名
* @return UserDetails * @return UserDetails
* @throws UsernameNotFoundException,TenantNotFoundException * @throws UsernameNotFoundException,TenantNotFoundException
*/ */
@Override @Override
public UserDetails loadUserByIdentifierAndTenantCode(String username, String tenantCode) throws UsernameNotFoundException, TenantNotFoundException { public UserDetails loadUserByIdentifierAndTenantCode(String tenantCode, String username) throws UsernameNotFoundException, TenantNotFoundException {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
Tenant tenant = this.validateTenantCode(tenantCode); ResponseBean<UserVo> userVoResponseBean = userServiceClient.findUserByIdentifier(username, tenantCode);
ResponseBean<UserVo> userVoResponseBean = userServiceClient.findUserByIdentifier(username, tenantCode); if (!ResponseUtil.isSuccess(userVoResponseBean))
if (!ResponseUtil.isSuccess(userVoResponseBean))
throw new ServiceException("查询用户信息失败: " + userVoResponseBean.getMsg()); throw new ServiceException("查询用户信息失败: " + userVoResponseBean.getMsg());
UserVo userVo = userVoResponseBean.getData(); UserVo userVo = userVoResponseBean.getData();
if (userVo == null) if (userVo == null)
throw new UsernameNotFoundException("用户不存在."); throw new UsernameNotFoundException("用户不存在.");
return new CustomUserDetails(username, userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), start, LoginType.PWD); return new CustomUserDetails(username, userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), start, LoginType.PWD);
} }
/** /**
* 根据社交账号查询 * 根据社交账号查询
* *
* @param tenantCode tenantCode
* @param social social * @param social social
* @param tenantCode tenantCode
* @param mobileUser mobileUser * @param mobileUser mobileUser
* @return UserDetails * @return UserDetails
* @author tangyi * @author tangyi
* @date 2019/06/22 21:08 * @date 2019/06/22 21:08
*/ */
@Override @Override
public UserDetails loadUserBySocialAndTenantCode(String social, String tenantCode, MobileUser mobileUser) throws UsernameNotFoundException { public UserDetails loadUserBySocialAndTenantCode(String tenantCode, String social, MobileUser mobileUser) throws UsernameNotFoundException {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
Tenant tenant = this.validateTenantCode(tenantCode); ResponseBean<UserVo> userVoResponseBean = userServiceClient.findUserByIdentifier(social, IdentityType.PHONE_NUMBER.getValue(), tenantCode);
ResponseBean<UserVo> userVoResponseBean = userServiceClient.findUserByIdentifier(social, IdentityType.PHONE_NUMBER.getValue(), tenantCode); if (!ResponseUtil.isSuccess(userVoResponseBean))
if (!ResponseUtil.isSuccess(userVoResponseBean)) throw new ServiceException("查询用户信息失败: " + userVoResponseBean.getMsg());
throw new ServiceException("查询用户信息失败: " + userVoResponseBean.getMsg()); UserVo userVo = userVoResponseBean.getData();
UserVo userVo = userVoResponseBean.getData(); // 第一次登录
// 第一次登录
if (userVo == null) { if (userVo == null) {
UserDto userDto = new UserDto(); UserDto userDto = new UserDto();
// 用户的基本信息 // 用户的基本信息
...@@ -106,19 +95,13 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService { ...@@ -106,19 +95,13 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
userDto.setLoginTime(DateUtils.asDate(LocalDateTime.now())); userDto.setLoginTime(DateUtils.asDate(LocalDateTime.now()));
// 注册账号 // 注册账号
ResponseBean<Boolean> response = userServiceClient.registerUser(userDto); ResponseBean<Boolean> response = userServiceClient.registerUser(userDto);
if (!ResponseUtil.isSuccess(response)) if (!ResponseUtil.isSuccess(response))
throw new ServiceException("自动注册用户失败: " + response.getMsg()); throw new ServiceException("自动注册用户失败: " + response.getMsg());
// 重新获取用户信息 // 重新获取用户信息
userVoResponseBean = userServiceClient.findUserByIdentifier(social, IdentityType.PHONE_NUMBER.getValue(), tenantCode); userVoResponseBean = userServiceClient.findUserByIdentifier(social, IdentityType.PHONE_NUMBER.getValue(), tenantCode);
if (!ResponseUtil.isSuccess(userVoResponseBean)) if (!ResponseUtil.isSuccess(userVoResponseBean))
throw new ServiceException("查询用户信息失败: " + userVoResponseBean.getMsg()); throw new ServiceException("查询用户信息失败: " + userVoResponseBean.getMsg());
userVo = userVoResponseBean.getData(); userVo = userVoResponseBean.getData();
} else {
// TODO 记录登录时间,IP等信息
UserDto userDto = new UserDto();
BeanUtils.copyProperties(userVo, userDto);
userDto.setLoginTime(DateUtils.asDate(LocalDateTime.now()));
//userServiceClient.updateUser(userDto);
} }
return new CustomUserDetails(userVo.getIdentifier(), userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), start, LoginType.SMS); return new CustomUserDetails(userVo.getIdentifier(), userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), start, LoginType.SMS);
} }
...@@ -127,26 +110,25 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService { ...@@ -127,26 +110,25 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
* 根据微信code和租户标识查询 * 根据微信code和租户标识查询
* 将code换成openId和sessionKey * 将code换成openId和sessionKey
* *
* @param tenantCode tenantCode
* @param code code * @param code code
* @param tenantCode tenantCode
* @param wxUser wxUser * @param wxUser wxUser
* @return UserDetails * @return UserDetails
* @author tangyi * @author tangyi
* @date 2019/07/05 20:05:36 * @date 2019/07/05 20:05:36
*/ */
@Override @Override
public UserDetails loadUserByWxCodeAndTenantCode(String code, String tenantCode, WxUser wxUser) throws UsernameNotFoundException { public UserDetails loadUserByWxCodeAndTenantCode(String tenantCode, String code, WxUser wxUser) throws UsernameNotFoundException {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
Tenant tenant = this.validateTenantCode(tenantCode);
// 根据code获取openId和sessionKey // 根据code获取openId和sessionKey
WxSession wxSession = wxService.code2Session(code); WxSession wxSession = wxService.code2Session(code);
if (wxSession == null) if (wxSession == null)
throw new CommonException("获取openId失败."); throw new CommonException("获取openId失败.");
// 获取用户信息 // 获取用户信息
ResponseBean<UserVo> userVoResponseBean = userServiceClient.findUserByIdentifier(wxSession.getOpenId(), IdentityType.WE_CHAT.getValue(), tenantCode); ResponseBean<UserVo> userVoResponseBean = userServiceClient.findUserByIdentifier(wxSession.getOpenId(), IdentityType.WE_CHAT.getValue(), tenantCode);
if (!ResponseUtil.isSuccess(userVoResponseBean)) if (!ResponseUtil.isSuccess(userVoResponseBean))
throw new ServiceException("查询用户信息失败: " + userVoResponseBean.getMsg()); throw new ServiceException("查询用户信息失败: " + userVoResponseBean.getMsg());
UserVo userVo = userVoResponseBean.getData(); UserVo userVo = userVoResponseBean.getData();
// 为空说明是第一次登录,需要将用户信息增加到数据库里 // 为空说明是第一次登录,需要将用户信息增加到数据库里
if (userVo == null) { if (userVo == null) {
UserDto userDto = new UserDto(); UserDto userDto = new UserDto();
...@@ -163,40 +145,14 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService { ...@@ -163,40 +145,14 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
throw new ServiceException("自动注册用户失败: " + response.getMsg()); throw new ServiceException("自动注册用户失败: " + response.getMsg());
// 重新获取用户信息 // 重新获取用户信息
userVoResponseBean = userServiceClient.findUserByIdentifier(wxSession.getOpenId(), IdentityType.WE_CHAT.getValue(), tenantCode); userVoResponseBean = userServiceClient.findUserByIdentifier(wxSession.getOpenId(), IdentityType.WE_CHAT.getValue(), tenantCode);
if (!ResponseUtil.isSuccess(userVoResponseBean)) if (!ResponseUtil.isSuccess(userVoResponseBean))
throw new ServiceException("查询用户信息失败: " + userVoResponseBean.getMsg()); throw new ServiceException("查询用户信息失败: " + userVoResponseBean.getMsg());
userVo = userVoResponseBean.getData(); userVo = userVoResponseBean.getData();
} else {
// TODO 更新sessionKey,记录登录时间,IP等信息
UserDto userDto = new UserDto();
BeanUtils.copyProperties(userVo, userDto);
//userDto.setCredential(wxSession.getSessionKey());
userDto.setLoginTime(DateUtils.asDate(LocalDateTime.now()));
//userServiceClient.updateUser(userDto);
} }
return new CustomUserDetails(userVo.getIdentifier(), userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), start, LoginType.WECHAT); return new CustomUserDetails(userVo.getIdentifier(), userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), start, LoginType.WECHAT);
} }
/** /**
* 校验租户标识
*
* @param tenantCode tenantCode
* @return Tenant
*/
private Tenant validateTenantCode(String tenantCode) throws TenantNotFoundException {
if (StringUtils.isBlank(tenantCode))
throw new TenantNotFoundException("租户code不能为空.");
// 先获取租户信息
ResponseBean<Tenant> tenantResponseBean = userServiceClient.findTenantByTenantCode(tenantCode);
if (!ResponseUtil.isSuccess(tenantResponseBean))
throw new ServiceException("查询租户信息失败: " + tenantResponseBean.getMsg());
Tenant tenant = tenantResponseBean.getData();
if (tenant == null)
throw new TenantNotFoundException("租户不存在.");
return tenant;
}
/**
* 获取用户权限 * 获取用户权限
* *
* @param userVo userVo * @param userVo userVo
...@@ -205,43 +161,9 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService { ...@@ -205,43 +161,9 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
* @date 2019/03/17 14:41 * @date 2019/03/17 14:41
*/ */
private Set<GrantedAuthority> getAuthority(UserVo userVo) { private Set<GrantedAuthority> getAuthority(UserVo userVo) {
// 权限集合 return userVo.getRoleList()
Set<GrantedAuthority> authorities = new HashSet<>(); .stream()
// 根据角色查找菜单权限 .map(role -> new GrantedAuthorityImpl(role.getRoleCode().toUpperCase()))
List<Menu> menus = Lists.newArrayList(); .collect(Collectors.toSet());
// 判断是否是管理员,是则查找所有菜单权限
if (userVo.getIdentifier().equals(sysProperties.getAdminUser())) {
// 查找所有菜单权限,因为角色一般是一个,这里只会执行一次
ResponseBean<List<Menu>> menusResponseBean = userServiceClient.findAllMenu(userVo.getTenantCode());
if (!ResponseUtil.isSuccess(menusResponseBean)) {
throw new ServiceException("查询所有菜单失败: " + menusResponseBean.getMsg());
}
menus = menusResponseBean.getData();
} else {
// 根据角色查询菜单权限
List<RoleVo> roleList = userVo.getRoleList();
if (CollectionUtils.isNotEmpty(roleList)) {
for (RoleVo role : roleList) {
// 根据角色查找菜单权限
ResponseBean<List<Menu>> roleMenusResponseBean = userServiceClient.findMenuByRole(role.getRoleCode(), userVo.getTenantCode());
if (!ResponseUtil.isSuccess(roleMenusResponseBean)) {
throw new ServiceException("查询角色菜单失败: " + roleMenusResponseBean.getMsg());
}
List<Menu> roleMenus = roleMenusResponseBean.getData();
if (CollectionUtils.isNotEmpty(roleMenus))
menus.addAll(roleMenus);
// 权限如果前缀是ROLE_,security就会认为这是个角色信息,而不是权限,例如ROLE_ADMIN就是ADMIN角色,MENU:ADD就是MENU:ADD权限
authorities.add(new GrantedAuthorityImpl(role.getRoleCode()));
}
}
}
if (CollectionUtils.isNotEmpty(menus)) {
// 菜单权限
List<GrantedAuthority> authorityList = menus.stream()
.filter(menu -> MenuConstant.MENU_TYPE_PERMISSION.equals(menu.getType()))
.map(menu -> new GrantedAuthorityImpl(menu.getPermission())).collect(Collectors.toList());
authorities.addAll(authorityList);
}
return authorities;
} }
} }
package com.github.tangyi.auth.security;
import com.github.tangyi.common.core.exceptions.ServiceException;
import com.github.tangyi.common.core.exceptions.TenantNotFoundException;
import com.github.tangyi.common.core.model.ResponseBean;
import com.github.tangyi.common.core.utils.ResponseUtil;
import com.github.tangyi.user.api.feign.UserServiceClient;
import com.github.tangyi.user.api.module.Tenant;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/**
*
* 校验租户
*
* @author tangyi
* @date 2019-11-12 20:14
*/
@AllArgsConstructor
@Aspect
@Component
public class ValidateTenantAspect {
private final UserServiceClient userServiceClient;
@Before("execution(* com.github.tangyi.auth.security.CustomUserDetailsServiceImpl.load*(..)) && args(tenantCode,..)")
public void validateTenantCode(String tenantCode) throws TenantNotFoundException {
// 获取tenantCode
if (StringUtils.isBlank(tenantCode))
throw new TenantNotFoundException("租户code不能为空.");
// 先获取租户信息
ResponseBean<Tenant> tenantResponseBean = userServiceClient.findTenantByTenantCode(tenantCode);
if (!ResponseUtil.isSuccess(tenantResponseBean))
throw new ServiceException("查询租户信息失败: " + tenantResponseBean.getMsg());
Tenant tenant = tenantResponseBean.getData();
if (tenant == null)
throw new TenantNotFoundException("租户不存在.");
}
}
...@@ -7,7 +7,7 @@ import com.github.tangyi.common.core.utils.PageUtil; ...@@ -7,7 +7,7 @@ import com.github.tangyi.common.core.utils.PageUtil;
import com.github.tangyi.common.core.utils.SysUtil; import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.annotations.AdminTenantTeacherAuthorization;
import com.github.tangyi.exam.api.module.Course; import com.github.tangyi.exam.api.module.Course;
import com.github.tangyi.exam.service.CourseService; import com.github.tangyi.exam.service.CourseService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
...@@ -17,7 +17,6 @@ import io.swagger.annotations.ApiOperation; ...@@ -17,7 +17,6 @@ import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
...@@ -93,7 +92,7 @@ public class CourseController extends BaseController { ...@@ -93,7 +92,7 @@ public class CourseController extends BaseController {
* @date 2018/11/10 21:31 * @date 2018/11/10 21:31
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('exam:course:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "创建课程", notes = "创建课程") @ApiOperation(value = "创建课程", notes = "创建课程")
@ApiImplicitParam(name = "course", value = "课程实体course", required = true, dataType = "Course") @ApiImplicitParam(name = "course", value = "课程实体course", required = true, dataType = "Course")
@Log("新增课程") @Log("新增课程")
...@@ -111,7 +110,7 @@ public class CourseController extends BaseController { ...@@ -111,7 +110,7 @@ public class CourseController extends BaseController {
* @date 2018/11/10 21:31 * @date 2018/11/10 21:31
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('exam:course:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "更新课程信息", notes = "根据课程id更新课程的基本信息") @ApiOperation(value = "更新课程信息", notes = "根据课程id更新课程的基本信息")
@ApiImplicitParam(name = "course", value = "课程实体course", required = true, dataType = "Course") @ApiImplicitParam(name = "course", value = "课程实体course", required = true, dataType = "Course")
@Log("更新课程") @Log("更新课程")
...@@ -129,7 +128,7 @@ public class CourseController extends BaseController { ...@@ -129,7 +128,7 @@ public class CourseController extends BaseController {
* @date 2018/11/10 21:32 * @date 2018/11/10 21:32
*/ */
@DeleteMapping("{id}") @DeleteMapping("{id}")
@PreAuthorize("hasAuthority('exam:course:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "删除课程", notes = "根据ID删除课程") @ApiOperation(value = "删除课程", notes = "根据ID删除课程")
@ApiImplicitParam(name = "id", value = "课程ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "课程ID", required = true, paramType = "path")
@Log("删除课程") @Log("删除课程")
...@@ -158,7 +157,7 @@ public class CourseController extends BaseController { ...@@ -158,7 +157,7 @@ public class CourseController extends BaseController {
* @date 2018/12/4 11:26 * @date 2018/12/4 11:26
*/ */
@PostMapping("deleteAll") @PostMapping("deleteAll")
@PreAuthorize("hasAuthority('exam:course:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "批量删除课程", notes = "根据课程id批量删除课程") @ApiOperation(value = "批量删除课程", notes = "根据课程id批量删除课程")
@ApiImplicitParam(name = "ids", value = "课程ID", dataType = "Long") @ApiImplicitParam(name = "ids", value = "课程ID", dataType = "Long")
@Log("批量删除课程") @Log("批量删除课程")
......
...@@ -4,11 +4,9 @@ import com.github.pagehelper.PageInfo; ...@@ -4,11 +4,9 @@ import com.github.pagehelper.PageInfo;
import com.github.tangyi.common.core.constant.CommonConstant; import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.model.ResponseBean; import com.github.tangyi.common.core.model.ResponseBean;
import com.github.tangyi.common.core.utils.*; import com.github.tangyi.common.core.utils.*;
import com.github.tangyi.common.core.vo.DeptVo;
import com.github.tangyi.common.core.vo.UserVo;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.annotations.AdminTenantTeacherAuthorization;
import com.github.tangyi.exam.api.dto.ExaminationRecordDto; import com.github.tangyi.exam.api.dto.ExaminationRecordDto;
import com.github.tangyi.exam.api.dto.StartExamDto; import com.github.tangyi.exam.api.dto.StartExamDto;
import com.github.tangyi.exam.api.enums.SubmitStatusEnum; import com.github.tangyi.exam.api.enums.SubmitStatusEnum;
...@@ -18,7 +16,6 @@ import com.github.tangyi.exam.service.AnswerService; ...@@ -18,7 +16,6 @@ import com.github.tangyi.exam.service.AnswerService;
import com.github.tangyi.exam.service.ExamRecordService; import com.github.tangyi.exam.service.ExamRecordService;
import com.github.tangyi.exam.service.ExaminationService; import com.github.tangyi.exam.service.ExaminationService;
import com.github.tangyi.exam.utils.ExamRecordUtil; import com.github.tangyi.exam.utils.ExamRecordUtil;
import com.github.tangyi.user.api.feign.UserServiceClient;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiImplicitParams;
...@@ -29,7 +26,6 @@ import org.apache.commons.collections4.CollectionUtils; ...@@ -29,7 +26,6 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
...@@ -58,8 +54,6 @@ public class ExamRecordController extends BaseController { ...@@ -58,8 +54,6 @@ public class ExamRecordController extends BaseController {
private final ExaminationService examinationService; private final ExaminationService examinationService;
private final UserServiceClient userServiceClient;
private final AnswerService answerService; private final AnswerService answerService;
/** /**
...@@ -113,55 +107,30 @@ public class ExamRecordController extends BaseController { ...@@ -113,55 +107,30 @@ public class ExamRecordController extends BaseController {
if (CollectionUtils.isNotEmpty(examRecordPageInfo.getList())) { if (CollectionUtils.isNotEmpty(examRecordPageInfo.getList())) {
// 查询考试信息 // 查询考试信息
List<Examination> examinations = examinationService.findListById(examRecordPageInfo.getList().stream().map(ExaminationRecord::getExaminationId).distinct().toArray(Long[]::new)); List<Examination> examinations = examinationService.findListById(examRecordPageInfo.getList().stream().map(ExaminationRecord::getExaminationId).distinct().toArray(Long[]::new));
// 查询用户信息 examRecordPageInfo.getList().forEach(tempExamRecord -> {
ResponseBean<List<UserVo>> returnT = userServiceClient.findUserById(examRecordPageInfo.getList().stream().map(ExaminationRecord::getUserId).distinct().toArray(Long[]::new)); // 找到考试记录所属的考试信息
if (returnT != null && CollectionUtils.isNotEmpty(returnT.getData())) { Examination examinationRecordExamination = examinations.stream()
examRecordPageInfo.getList().forEach(tempExamRecord -> { .filter(tempExamination -> tempExamRecord.getExaminationId().equals(tempExamination.getId()))
// 找到考试记录所属的考试信息 .findFirst().orElse(null);
Examination examinationRecordExamination = examinations.stream() // 转换成ExamRecordDto
.filter(tempExamination -> tempExamRecord.getExaminationId().equals(tempExamination.getId())) if (examinationRecordExamination != null) {
.findFirst().orElse(null); ExaminationRecordDto examRecordDto = new ExaminationRecordDto();
// 转换成ExamRecordDto BeanUtils.copyProperties(examinationRecordExamination, examRecordDto);
if (examinationRecordExamination != null) { examRecordDto.setId(tempExamRecord.getId());
ExaminationRecordDto examRecordDto = new ExaminationRecordDto(); examRecordDto.setStartTime(tempExamRecord.getStartTime());
BeanUtils.copyProperties(examinationRecordExamination, examRecordDto); examRecordDto.setEndTime(tempExamRecord.getEndTime());
examRecordDto.setId(tempExamRecord.getId()); examRecordDto.setScore(tempExamRecord.getScore());
examRecordDto.setStartTime(tempExamRecord.getStartTime()); examRecordDto.setUserId(tempExamRecord.getUserId());
examRecordDto.setEndTime(tempExamRecord.getEndTime()); examRecordDto.setExaminationId(tempExamRecord.getExaminationId());
examRecordDto.setScore(tempExamRecord.getScore()); // 正确题目数
examRecordDto.setUserId(tempExamRecord.getUserId()); examRecordDto.setCorrectNumber(tempExamRecord.getCorrectNumber());
examRecordDto.setExaminationId(tempExamRecord.getExaminationId()); examRecordDto.setInCorrectNumber(tempExamRecord.getInCorrectNumber());
// 正确题目数 // 提交状态
examRecordDto.setCorrectNumber(tempExamRecord.getCorrectNumber()); examRecordDto.setSubmitStatus(tempExamRecord.getSubmitStatus());
examRecordDto.setInCorrectNumber(tempExamRecord.getInCorrectNumber()); examRecordDtoList.add(examRecordDto);
// 提交状态 }
examRecordDto.setSubmitStatus(tempExamRecord.getSubmitStatus()); });
examRecordDtoList.add(examRecordDto); examRecordService.fillExamUserInfo(examRecordDtoList, examRecordPageInfo.getList().stream().map(ExaminationRecord::getUserId).distinct().toArray(Long[]::new));
}
});
// 查询部门信息
ResponseBean<List<DeptVo>> deptResponseBean = userServiceClient.findDeptById(returnT.getData().stream().map(UserVo::getDeptId).distinct().toArray(Long[]::new));
examRecordDtoList.forEach(tempExamRecordDto -> {
// 查询、设置用户信息
UserVo examRecordDtoUserVo = returnT.getData().stream()
.filter(tempUserVo -> tempExamRecordDto.getUserId().equals(tempUserVo.getId()))
.findFirst().orElse(null);
if (examRecordDtoUserVo != null) {
// 设置用户名
tempExamRecordDto.setUserName(examRecordDtoUserVo.getName());
// 查询、设置部门信息
if (deptResponseBean != null && CollectionUtils.isNotEmpty(deptResponseBean.getData())) {
DeptVo examRecordDtoDeptVo = deptResponseBean.getData().stream()
// 根据部门ID过滤
.filter(tempDept -> tempDept.getId().equals(examRecordDtoUserVo.getDeptId()))
.findFirst().orElse(null);
// 设置部门名称
if (examRecordDtoDeptVo != null)
tempExamRecordDto.setDeptName(examRecordDtoDeptVo.getDeptName());
}
}
});
}
} }
examRecordDtoPageInfo.setTotal(examRecordPageInfo.getTotal()); examRecordDtoPageInfo.setTotal(examRecordPageInfo.getTotal());
examRecordDtoPageInfo.setPages(examRecordPageInfo.getPages()); examRecordDtoPageInfo.setPages(examRecordPageInfo.getPages());
...@@ -184,10 +153,6 @@ public class ExamRecordController extends BaseController { ...@@ -184,10 +153,6 @@ public class ExamRecordController extends BaseController {
@ApiImplicitParam(name = "examRecord", value = "考试记录实体examRecord", required = true, dataType = "ExamRecord") @ApiImplicitParam(name = "examRecord", value = "考试记录实体examRecord", required = true, dataType = "ExamRecord")
@Log("新增考试记录") @Log("新增考试记录")
public ResponseBean<ExaminationRecord> addExamRecord(@RequestBody @Valid ExaminationRecord examRecord) { public ResponseBean<ExaminationRecord> addExamRecord(@RequestBody @Valid ExaminationRecord examRecord) {
Examination examination = new Examination();
examination.setId(examRecord.getExaminationId());
// 查找考试信息
examination = examinationService.get(examination);
examRecord.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode()); examRecord.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
examRecord.setStartTime(examRecord.getCreateDate()); examRecord.setStartTime(examRecord.getCreateDate());
examRecordService.insert(examRecord); examRecordService.insert(examRecord);
...@@ -245,7 +210,7 @@ public class ExamRecordController extends BaseController { ...@@ -245,7 +210,7 @@ public class ExamRecordController extends BaseController {
* @date 2018/12/31 22:28 * @date 2018/12/31 22:28
*/ */
@PostMapping("export") @PostMapping("export")
@PreAuthorize("hasAuthority('exam:examRecord:export') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "导出考试成绩", notes = "根据成绩id导出成绩") @ApiOperation(value = "导出考试成绩", notes = "根据成绩id导出成绩")
@ApiImplicitParam(name = "ids", value = "成绩ID", required = true, dataType = "Long") @ApiImplicitParam(name = "ids", value = "成绩ID", required = true, dataType = "Long")
@Log("导出考试记录") @Log("导出考试记录")
...@@ -292,30 +257,7 @@ public class ExamRecordController extends BaseController { ...@@ -292,30 +257,7 @@ public class ExamRecordController extends BaseController {
examRecordDtoList.add(recordDto); examRecordDtoList.add(recordDto);
} }
}); });
// 查询用户信息 examRecordService.fillExamUserInfo(examRecordDtoList, userIdSet.toArray(new Long[0]));
ResponseBean<List<UserVo>> returnT = userServiceClient.findUserById(userIdSet.toArray(new Long[0]));
if (returnT != null && CollectionUtils.isNotEmpty(returnT.getData())) {
// 获取部门信息
ResponseBean<List<DeptVo>> deptResponseBean = userServiceClient.findDeptById(returnT.getData().stream().map(UserVo::getDeptId).distinct().toArray(Long[]::new));
examRecordDtoList.forEach(tempExamRecordDto -> {
// 查询用户信息
UserVo examRecordDtoUserVo = returnT.getData().stream().filter(tempUserVo -> tempExamRecordDto.getUserId().equals(tempUserVo.getId()))
.findFirst().orElse(null);
if (examRecordDtoUserVo != null) {
tempExamRecordDto.setUserName(examRecordDtoUserVo.getName());
// 查询部门信息
if (deptResponseBean != null && CollectionUtils.isNotEmpty(deptResponseBean.getData())) {
// 查找用户所属部门
DeptVo examRecordDtoDeptVo = deptResponseBean.getData().stream()
.filter(tempDept -> tempDept.getId().equals(examRecordDtoUserVo.getDeptId()))
.findFirst().orElse(null);
// 设置所属部门名称
if (examRecordDtoDeptVo != null)
tempExamRecordDto.setDeptName(examRecordDtoDeptVo.getDeptName());
}
}
});
}
// 导出 // 导出
ExcelToolUtil.exportExcel(request.getInputStream(), response.getOutputStream(), MapUtil.java2Map(examRecordDtoList), ExamRecordUtil.getExamRecordDtoMap()); ExcelToolUtil.exportExcel(request.getInputStream(), response.getOutputStream(), MapUtil.java2Map(examRecordDtoList), ExamRecordUtil.getExamRecordDtoMap());
} }
......
...@@ -7,8 +7,7 @@ import com.github.tangyi.common.core.utils.PageUtil; ...@@ -7,8 +7,7 @@ import com.github.tangyi.common.core.utils.PageUtil;
import com.github.tangyi.common.core.utils.SysUtil; import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.annotations.AdminTenantTeacherAuthorization;
import com.github.tangyi.exam.api.dto.AnswerCartDto;
import com.github.tangyi.exam.api.dto.ExaminationDto; import com.github.tangyi.exam.api.dto.ExaminationDto;
import com.github.tangyi.exam.api.dto.SubjectDto; import com.github.tangyi.exam.api.dto.SubjectDto;
import com.github.tangyi.exam.api.module.Course; import com.github.tangyi.exam.api.module.Course;
...@@ -25,7 +24,6 @@ import lombok.extern.slf4j.Slf4j; ...@@ -25,7 +24,6 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
...@@ -152,7 +150,7 @@ public class ExaminationController extends BaseController { ...@@ -152,7 +150,7 @@ public class ExaminationController extends BaseController {
* @date 2018/11/10 21:14 * @date 2018/11/10 21:14
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('exam:exam:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "创建考试", notes = "创建考试") @ApiOperation(value = "创建考试", notes = "创建考试")
@ApiImplicitParam(name = "examinationDto", value = "考试实体examinationDto", required = true, dataType = "ExaminationDto") @ApiImplicitParam(name = "examinationDto", value = "考试实体examinationDto", required = true, dataType = "ExaminationDto")
@Log("新增考试") @Log("新增考试")
...@@ -173,7 +171,7 @@ public class ExaminationController extends BaseController { ...@@ -173,7 +171,7 @@ public class ExaminationController extends BaseController {
* @date 2018/11/10 21:15 * @date 2018/11/10 21:15
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('exam:exam:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "更新考试信息", notes = "根据考试id更新考试的基本信息") @ApiOperation(value = "更新考试信息", notes = "根据考试id更新考试的基本信息")
@ApiImplicitParam(name = "examinationDto", value = "考试实体answer", required = true, dataType = "ExaminationDto") @ApiImplicitParam(name = "examinationDto", value = "考试实体answer", required = true, dataType = "ExaminationDto")
@Log("更新考试") @Log("更新考试")
...@@ -195,7 +193,7 @@ public class ExaminationController extends BaseController { ...@@ -195,7 +193,7 @@ public class ExaminationController extends BaseController {
* @date 2018/11/10 21:20 * @date 2018/11/10 21:20
*/ */
@DeleteMapping("{id}") @DeleteMapping("{id}")
@PreAuthorize("hasAuthority('exam:exam:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "删除考试", notes = "根据ID删除考试") @ApiOperation(value = "删除考试", notes = "根据ID删除考试")
@ApiImplicitParam(name = "id", value = "考试ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "考试ID", required = true, paramType = "path")
@Log("删除考试") @Log("删除考试")
...@@ -224,7 +222,7 @@ public class ExaminationController extends BaseController { ...@@ -224,7 +222,7 @@ public class ExaminationController extends BaseController {
* @date 2018/12/03 22:03 * @date 2018/12/03 22:03
*/ */
@PostMapping("deleteAll") @PostMapping("deleteAll")
@PreAuthorize("hasAuthority('exam:exam:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "批量删除考试", notes = "根据考试id批量删除考试") @ApiOperation(value = "批量删除考试", notes = "根据考试id批量删除考试")
@ApiImplicitParam(name = "ids", value = "考试ID", dataType = "Long") @ApiImplicitParam(name = "ids", value = "考试ID", dataType = "Long")
@Log("批量删除考试") @Log("批量删除考试")
......
...@@ -7,7 +7,7 @@ import com.github.tangyi.common.core.utils.SysUtil; ...@@ -7,7 +7,7 @@ import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.utils.TreeUtil; import com.github.tangyi.common.core.utils.TreeUtil;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.annotations.AdminTenantTeacherAuthorization;
import com.github.tangyi.exam.api.constants.ExamSubjectConstant; import com.github.tangyi.exam.api.constants.ExamSubjectConstant;
import com.github.tangyi.exam.api.dto.SubjectCategoryDto; import com.github.tangyi.exam.api.dto.SubjectCategoryDto;
import com.github.tangyi.exam.api.module.SubjectCategory; import com.github.tangyi.exam.api.module.SubjectCategory;
...@@ -17,7 +17,6 @@ import io.swagger.annotations.ApiImplicitParam; ...@@ -17,7 +17,6 @@ import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
...@@ -89,7 +88,7 @@ public class SubjectCategoryController extends BaseController { ...@@ -89,7 +88,7 @@ public class SubjectCategoryController extends BaseController {
* @date 2018/12/04 22:00 * @date 2018/12/04 22:00
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('exam:subject:category:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "创建分类", notes = "创建分类") @ApiOperation(value = "创建分类", notes = "创建分类")
@ApiImplicitParam(name = "subjectCategory", value = "分类实体subjectCategory", required = true, dataType = "SubjectCategory") @ApiImplicitParam(name = "subjectCategory", value = "分类实体subjectCategory", required = true, dataType = "SubjectCategory")
@Log("新增题目分类") @Log("新增题目分类")
...@@ -108,7 +107,7 @@ public class SubjectCategoryController extends BaseController { ...@@ -108,7 +107,7 @@ public class SubjectCategoryController extends BaseController {
* @date 2018/12/04 22:01 * @date 2018/12/04 22:01
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('exam:subject:category:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "更新分类信息", notes = "根据分类id更新分类的基本信息") @ApiOperation(value = "更新分类信息", notes = "根据分类id更新分类的基本信息")
@ApiImplicitParam(name = "subjectCategory", value = "分类实体subjectCategory", required = true, dataType = "SubjectCategory") @ApiImplicitParam(name = "subjectCategory", value = "分类实体subjectCategory", required = true, dataType = "SubjectCategory")
@Log("更新题目分类") @Log("更新题目分类")
...@@ -126,7 +125,7 @@ public class SubjectCategoryController extends BaseController { ...@@ -126,7 +125,7 @@ public class SubjectCategoryController extends BaseController {
* @date 2018/12/04 22:02 * @date 2018/12/04 22:02
*/ */
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
@PreAuthorize("hasAuthority('exam:subject:category:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "删除分类", notes = "根据ID删除分类") @ApiOperation(value = "删除分类", notes = "根据ID删除分类")
@ApiImplicitParam(name = "id", value = "分类ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "分类ID", required = true, paramType = "path")
@Log("删除题目分类") @Log("删除题目分类")
......
...@@ -7,7 +7,7 @@ import com.github.tangyi.common.core.model.ResponseBean; ...@@ -7,7 +7,7 @@ import com.github.tangyi.common.core.model.ResponseBean;
import com.github.tangyi.common.core.utils.*; import com.github.tangyi.common.core.utils.*;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.annotations.AdminTenantTeacherAuthorization;
import com.github.tangyi.exam.api.dto.SubjectDto; import com.github.tangyi.exam.api.dto.SubjectDto;
import com.github.tangyi.exam.service.AnswerService; import com.github.tangyi.exam.service.AnswerService;
import com.github.tangyi.exam.service.SubjectService; import com.github.tangyi.exam.service.SubjectService;
...@@ -17,7 +17,6 @@ import io.swagger.annotations.*; ...@@ -17,7 +17,6 @@ import io.swagger.annotations.*;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
...@@ -101,7 +100,7 @@ public class SubjectController extends BaseController { ...@@ -101,7 +100,7 @@ public class SubjectController extends BaseController {
* @date 2018/11/10 21:43 * @date 2018/11/10 21:43
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('exam:exam:subject:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "创建题目", notes = "创建题目") @ApiOperation(value = "创建题目", notes = "创建题目")
@ApiImplicitParam(name = "subject", value = "题目信息", required = true, dataType = "SubjectDto") @ApiImplicitParam(name = "subject", value = "题目信息", required = true, dataType = "SubjectDto")
@Log("新增题目") @Log("新增题目")
...@@ -119,7 +118,7 @@ public class SubjectController extends BaseController { ...@@ -119,7 +118,7 @@ public class SubjectController extends BaseController {
* @date 2018/11/10 21:43 * @date 2018/11/10 21:43
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('exam:exam:subject:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "更新题目信息", notes = "根据题目id更新题目的基本信息") @ApiOperation(value = "更新题目信息", notes = "根据题目id更新题目的基本信息")
@ApiImplicitParam(name = "subject", value = "角色实体subject", required = true, dataType = "Subject") @ApiImplicitParam(name = "subject", value = "角色实体subject", required = true, dataType = "Subject")
@Log("更新题目") @Log("更新题目")
...@@ -137,7 +136,7 @@ public class SubjectController extends BaseController { ...@@ -137,7 +136,7 @@ public class SubjectController extends BaseController {
* @date 2018/11/10 21:43 * @date 2018/11/10 21:43
*/ */
@DeleteMapping("{id}") @DeleteMapping("{id}")
@PreAuthorize("hasAuthority('exam:exam:subject:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "删除题目", notes = "根据ID删除题目") @ApiOperation(value = "删除题目", notes = "根据ID删除题目")
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "题目ID", required = true, dataType = "Long", paramType = "path"), @ApiImplicitParam(name = "id", value = "题目ID", required = true, dataType = "Long", paramType = "path"),
...@@ -161,7 +160,7 @@ public class SubjectController extends BaseController { ...@@ -161,7 +160,7 @@ public class SubjectController extends BaseController {
* @date 2018/11/28 12:53 * @date 2018/11/28 12:53
*/ */
@PostMapping("export") @PostMapping("export")
@PreAuthorize("hasAuthority('exam:exam:subject:export') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "导出题目", notes = "根据分类id导出题目") @ApiOperation(value = "导出题目", notes = "根据分类id导出题目")
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(name = "ids", value = "题目ID", required = true, dataType = "Long"), @ApiImplicitParam(name = "ids", value = "题目ID", required = true, dataType = "Long"),
...@@ -200,7 +199,7 @@ public class SubjectController extends BaseController { ...@@ -200,7 +199,7 @@ public class SubjectController extends BaseController {
* @date 2018/11/28 12:59 * @date 2018/11/28 12:59
*/ */
@RequestMapping("import") @RequestMapping("import")
@PreAuthorize("hasAuthority('exam:exam:subject:import') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "导入题目", notes = "导入题目") @ApiOperation(value = "导入题目", notes = "导入题目")
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(name = "examinationId", value = "考试ID", dataType = "Long"), @ApiImplicitParam(name = "examinationId", value = "考试ID", dataType = "Long"),
...@@ -232,7 +231,7 @@ public class SubjectController extends BaseController { ...@@ -232,7 +231,7 @@ public class SubjectController extends BaseController {
* @date 2018/12/04 9:55 * @date 2018/12/04 9:55
*/ */
@PostMapping("deleteAll") @PostMapping("deleteAll")
@PreAuthorize("hasAuthority('exam:exam:subject:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "批量删除题目", notes = "根据题目id批量删除题目") @ApiOperation(value = "批量删除题目", notes = "根据题目id批量删除题目")
@ApiImplicitParam(name = "ids", value = "题目ID", dataType = "Long") @ApiImplicitParam(name = "ids", value = "题目ID", dataType = "Long")
@Log("批量删除题目") @Log("批量删除题目")
......
package com.github.tangyi.exam.service; package com.github.tangyi.exam.service;
import com.github.tangyi.common.core.constant.CommonConstant; import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.model.ResponseBean;
import com.github.tangyi.common.core.service.CrudService; import com.github.tangyi.common.core.service.CrudService;
import com.github.tangyi.common.core.utils.ResponseUtil;
import com.github.tangyi.common.core.vo.DeptVo;
import com.github.tangyi.common.core.vo.UserVo;
import com.github.tangyi.exam.api.dto.ExaminationRecordDto;
import com.github.tangyi.exam.api.module.ExaminationRecord; import com.github.tangyi.exam.api.module.ExaminationRecord;
import com.github.tangyi.exam.mapper.ExamRecordMapper; import com.github.tangyi.exam.mapper.ExamRecordMapper;
import com.github.tangyi.user.api.feign.UserServiceClient;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/** /**
* 考试记录service * 考试记录service
* *
...@@ -20,6 +29,8 @@ import org.springframework.transaction.annotation.Transactional; ...@@ -20,6 +29,8 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class ExamRecordService extends CrudService<ExamRecordMapper, ExaminationRecord> { public class ExamRecordService extends CrudService<ExamRecordMapper, ExaminationRecord> {
private final UserServiceClient userServiceClient;
/** /**
* 查询考试记录 * 查询考试记录
* *
...@@ -90,4 +101,40 @@ public class ExamRecordService extends CrudService<ExamRecordMapper, Examination ...@@ -90,4 +101,40 @@ public class ExamRecordService extends CrudService<ExamRecordMapper, Examination
public int deleteAll(Long[] ids) { public int deleteAll(Long[] ids) {
return super.deleteAll(ids); return super.deleteAll(ids);
} }
/**
* 获取用户、部门相关信息
* @param examRecordDtoList examRecordDtoList
* @param userIds userIds
*/
public void fillExamUserInfo(List<ExaminationRecordDto> examRecordDtoList, Long[] userIds) {
// 查询用户信息
ResponseBean<List<UserVo>> returnT = userServiceClient.findUserById(userIds);
if (ResponseUtil.isSuccess(returnT)) {
// 查询部门信息
ResponseBean<List<DeptVo>> deptResponseBean = userServiceClient.findDeptById(returnT.getData().stream().map(UserVo::getDeptId).distinct().toArray(Long[]::new));
if (ResponseUtil.isSuccess(deptResponseBean)) {
examRecordDtoList.forEach(tempExamRecordDto -> {
// 查询、设置用户信息
UserVo examRecordDtoUserVo = returnT.getData().stream()
.filter(tempUserVo -> tempExamRecordDto.getUserId().equals(tempUserVo.getId()))
.findFirst().orElse(null);
if (examRecordDtoUserVo != null) {
// 设置用户名
tempExamRecordDto.setUserName(examRecordDtoUserVo.getName());
// 查询、设置部门信息
if (CollectionUtils.isNotEmpty(deptResponseBean.getData())) {
DeptVo examRecordDtoDeptVo = deptResponseBean.getData().stream()
// 根据部门ID过滤
.filter(tempDept -> tempDept.getId().equals(examRecordDtoUserVo.getDeptId()))
.findFirst().orElse(null);
// 设置部门名称
if (examRecordDtoDeptVo != null)
tempExamRecordDto.setDeptName(examRecordDtoDeptVo.getDeptName());
}
}
});
}
}
}
} }
...@@ -5,7 +5,6 @@ import com.github.tangyi.common.core.constant.CommonConstant; ...@@ -5,7 +5,6 @@ import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.service.CrudService; import com.github.tangyi.common.core.service.CrudService;
import com.github.tangyi.common.core.utils.PageUtil; import com.github.tangyi.common.core.utils.PageUtil;
import com.github.tangyi.common.core.utils.SysUtil; import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.exam.api.dto.AnswerCartDto;
import com.github.tangyi.exam.api.dto.SubjectDto; import com.github.tangyi.exam.api.dto.SubjectDto;
import com.github.tangyi.exam.api.module.Examination; import com.github.tangyi.exam.api.module.Examination;
import com.github.tangyi.exam.api.module.ExaminationSubject; import com.github.tangyi.exam.api.module.ExaminationSubject;
......
...@@ -23,7 +23,6 @@ import java.util.HashMap; ...@@ -23,7 +23,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
/** /**
* 题目service * 题目service
......
...@@ -45,5 +45,28 @@ public class MenuConstant { ...@@ -45,5 +45,28 @@ public class MenuConstant {
* 修改 * 修改
*/ */
public static final String PERMISSION_SUFFIX_MODIFY = ":edit"; public static final String PERMISSION_SUFFIX_MODIFY = ":edit";
public static final String MENU_SYS = "sys";
/**
* 终端管理
*/
public static final String MENU_CLIENT = "sys:client";
/**
* 路由管理
*/
public static final String MENU_ROUTE = "sys:route";
/**
* 租户中心
*/
public static final String MENU_TENANT = "tenant";
/**
* 系统监控
*/
public static final String MENU_MONITOR = "monitor";
} }
...@@ -8,7 +8,7 @@ import com.github.tangyi.common.core.utils.TreeUtil; ...@@ -8,7 +8,7 @@ import com.github.tangyi.common.core.utils.TreeUtil;
import com.github.tangyi.common.core.vo.DeptVo; import com.github.tangyi.common.core.vo.DeptVo;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.annotations.AdminTenantTeacherAuthorization;
import com.github.tangyi.user.api.dto.DeptDto; import com.github.tangyi.user.api.dto.DeptDto;
import com.github.tangyi.user.api.module.Dept; import com.github.tangyi.user.api.module.Dept;
import com.github.tangyi.user.service.DeptService; import com.github.tangyi.user.service.DeptService;
...@@ -17,7 +17,6 @@ import io.swagger.annotations.ApiImplicitParam; ...@@ -17,7 +17,6 @@ import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
...@@ -91,7 +90,7 @@ public class DeptController extends BaseController { ...@@ -91,7 +90,7 @@ public class DeptController extends BaseController {
* @date 2018/8/28 10:15 * @date 2018/8/28 10:15
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('sys:dept:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "创建部门", notes = "创建部门") @ApiOperation(value = "创建部门", notes = "创建部门")
@ApiImplicitParam(name = "dept", value = "部门实体", required = true, dataType = "Dept") @ApiImplicitParam(name = "dept", value = "部门实体", required = true, dataType = "Dept")
@Log("新增部门") @Log("新增部门")
...@@ -109,7 +108,7 @@ public class DeptController extends BaseController { ...@@ -109,7 +108,7 @@ public class DeptController extends BaseController {
* @date 2018/8/28 10:16 * @date 2018/8/28 10:16
*/ */
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
@PreAuthorize("hasAuthority('sys:dept:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "删除部门", notes = "根据ID删除部门") @ApiOperation(value = "删除部门", notes = "根据ID删除部门")
@ApiImplicitParam(name = "id", value = "部门ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "部门ID", required = true, paramType = "path")
@Log("删除部门") @Log("删除部门")
...@@ -129,7 +128,7 @@ public class DeptController extends BaseController { ...@@ -129,7 +128,7 @@ public class DeptController extends BaseController {
* @date 2018/8/28 10:22 * @date 2018/8/28 10:22
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('sys:dept:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "更新部门信息", notes = "根据部门id更新部门的基本信息") @ApiOperation(value = "更新部门信息", notes = "根据部门id更新部门的基本信息")
@ApiImplicitParam(name = "dept", value = "部门实体", required = true, dataType = "Dept") @ApiImplicitParam(name = "dept", value = "部门实体", required = true, dataType = "Dept")
@Log("更新部门") @Log("更新部门")
......
...@@ -7,7 +7,7 @@ import com.github.tangyi.common.core.model.ResponseBean; ...@@ -7,7 +7,7 @@ import com.github.tangyi.common.core.model.ResponseBean;
import com.github.tangyi.common.core.utils.PageUtil; import com.github.tangyi.common.core.utils.PageUtil;
import com.github.tangyi.common.core.utils.SysUtil; import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.annotations.AdminAuthorization;
import com.github.tangyi.user.service.LogService; import com.github.tangyi.user.service.LogService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
...@@ -16,7 +16,6 @@ import io.swagger.annotations.ApiOperation; ...@@ -16,7 +16,6 @@ import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
...@@ -98,10 +97,6 @@ public class LogController extends BaseController { ...@@ -98,10 +97,6 @@ public class LogController extends BaseController {
@ApiOperation(value = "新增日志", notes = "新增日志") @ApiOperation(value = "新增日志", notes = "新增日志")
@ApiImplicitParam(name = "log", value = "日志实体Log", required = true, dataType = "Log") @ApiImplicitParam(name = "log", value = "日志实体Log", required = true, dataType = "Log")
public ResponseBean<Boolean> addLog(@RequestBody @Valid Log log) { public ResponseBean<Boolean> addLog(@RequestBody @Valid Log log) {
if (log.getId() != null)
log.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
if (true)
return null;
// 保存日志 // 保存日志
return new ResponseBean<>(logService.insert(log) > 0); return new ResponseBean<>(logService.insert(log) > 0);
} }
...@@ -115,7 +110,7 @@ public class LogController extends BaseController { ...@@ -115,7 +110,7 @@ public class LogController extends BaseController {
* @date 2018/10/31 21:27 * @date 2018/10/31 21:27
*/ */
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
@PreAuthorize("hasAuthority('monitor:log:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminAuthorization
@ApiOperation(value = "删除日志", notes = "根据ID删除日志") @ApiOperation(value = "删除日志", notes = "根据ID删除日志")
@ApiImplicitParam(name = "id", value = "日志ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "日志ID", required = true, paramType = "path")
public ResponseBean<Boolean> delete(@PathVariable Long id) { public ResponseBean<Boolean> delete(@PathVariable Long id) {
...@@ -133,7 +128,7 @@ public class LogController extends BaseController { ...@@ -133,7 +128,7 @@ public class LogController extends BaseController {
* @date 2018/12/4 10:12 * @date 2018/12/4 10:12
*/ */
@PostMapping("deleteAll") @PostMapping("deleteAll")
@PreAuthorize("hasAuthority('monitor:log:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminAuthorization
@ApiOperation(value = "批量删除日志", notes = "根据日志ids批量删除日志") @ApiOperation(value = "批量删除日志", notes = "根据日志ids批量删除日志")
@ApiImplicitParam(name = "ids", value = "日志ID", dataType = "Long") @ApiImplicitParam(name = "ids", value = "日志ID", dataType = "Long")
public ResponseBean<Boolean> deleteAllLog(@RequestBody Long[] ids) { public ResponseBean<Boolean> deleteAllLog(@RequestBody Long[] ids) {
......
...@@ -7,7 +7,7 @@ import com.github.tangyi.common.core.model.ResponseBean; ...@@ -7,7 +7,7 @@ import com.github.tangyi.common.core.model.ResponseBean;
import com.github.tangyi.common.core.utils.*; import com.github.tangyi.common.core.utils.*;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.annotations.AdminTenantTeacherAuthorization;
import com.github.tangyi.user.api.dto.MenuDto; import com.github.tangyi.user.api.dto.MenuDto;
import com.github.tangyi.user.api.module.Menu; import com.github.tangyi.user.api.module.Menu;
import com.github.tangyi.user.service.MenuService; import com.github.tangyi.user.service.MenuService;
...@@ -17,7 +17,6 @@ import io.swagger.annotations.*; ...@@ -17,7 +17,6 @@ import io.swagger.annotations.*;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
...@@ -90,7 +89,7 @@ public class MenuController extends BaseController { ...@@ -90,7 +89,7 @@ public class MenuController extends BaseController {
* @date 2018/8/27 16:12 * @date 2018/8/27 16:12
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('sys:menu:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "创建菜单", notes = "创建菜单") @ApiOperation(value = "创建菜单", notes = "创建菜单")
@ApiImplicitParam(name = "menu", value = "角色实体menu", required = true, dataType = "Menu") @ApiImplicitParam(name = "menu", value = "角色实体menu", required = true, dataType = "Menu")
@Log("新增菜单") @Log("新增菜单")
...@@ -108,7 +107,7 @@ public class MenuController extends BaseController { ...@@ -108,7 +107,7 @@ public class MenuController extends BaseController {
* @date 2018/10/24 16:34 * @date 2018/10/24 16:34
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('sys:menu:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "更新菜单信息", notes = "根据菜单id更新菜单的基本信息") @ApiOperation(value = "更新菜单信息", notes = "根据菜单id更新菜单的基本信息")
@ApiImplicitParam(name = "menu", value = "角色实体menu", required = true, dataType = "Menu") @ApiImplicitParam(name = "menu", value = "角色实体menu", required = true, dataType = "Menu")
@Log("更新菜单") @Log("更新菜单")
...@@ -126,7 +125,7 @@ public class MenuController extends BaseController { ...@@ -126,7 +125,7 @@ public class MenuController extends BaseController {
* @date 2018/8/27 16:19 * @date 2018/8/27 16:19
*/ */
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
@PreAuthorize("hasAuthority('sys:menu:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "删除菜单", notes = "根据ID删除菜单") @ApiOperation(value = "删除菜单", notes = "根据ID删除菜单")
@ApiImplicitParam(name = "id", value = "菜单ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "菜单ID", required = true, paramType = "path")
@Log("删除菜单") @Log("删除菜单")
...@@ -243,7 +242,7 @@ public class MenuController extends BaseController { ...@@ -243,7 +242,7 @@ public class MenuController extends BaseController {
* @date 2018/11/28 12:46 * @date 2018/11/28 12:46
*/ */
@PostMapping("export") @PostMapping("export")
@PreAuthorize("hasAuthority('sys:menu:export') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "导出菜单", notes = "根据菜单id导出菜单") @ApiOperation(value = "导出菜单", notes = "根据菜单id导出菜单")
@ApiImplicitParam(name = "ids", value = "菜单ID", required = true, dataType = "Long") @ApiImplicitParam(name = "ids", value = "菜单ID", required = true, dataType = "Long")
@Log("导出菜单") @Log("导出菜单")
...@@ -280,7 +279,7 @@ public class MenuController extends BaseController { ...@@ -280,7 +279,7 @@ public class MenuController extends BaseController {
* @date 2018/11/28 12:51 * @date 2018/11/28 12:51
*/ */
@PostMapping("import") @PostMapping("import")
@PreAuthorize("hasAuthority('sys:menu:import') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "导入菜单", notes = "导入菜单") @ApiOperation(value = "导入菜单", notes = "导入菜单")
@Log("导入菜单") @Log("导入菜单")
public ResponseBean<Boolean> importMenu(@ApiParam(value = "要上传的文件", required = true) MultipartFile file) { public ResponseBean<Boolean> importMenu(@ApiParam(value = "要上传的文件", required = true) MultipartFile file) {
......
...@@ -7,7 +7,7 @@ import com.github.tangyi.common.core.utils.PageUtil; ...@@ -7,7 +7,7 @@ import com.github.tangyi.common.core.utils.PageUtil;
import com.github.tangyi.common.core.utils.SysUtil; import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.annotations.AdminTenantTeacherAuthorization;
import com.github.tangyi.user.api.module.Role; import com.github.tangyi.user.api.module.Role;
import com.github.tangyi.user.service.RoleMenuService; import com.github.tangyi.user.service.RoleMenuService;
import com.github.tangyi.user.service.RoleService; import com.github.tangyi.user.service.RoleService;
...@@ -19,7 +19,6 @@ import lombok.AllArgsConstructor; ...@@ -19,7 +19,6 @@ import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
...@@ -120,7 +119,7 @@ public class RoleController extends BaseController { ...@@ -120,7 +119,7 @@ public class RoleController extends BaseController {
* @date 2018/9/14 18:22 * @date 2018/9/14 18:22
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('sys:role:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "更新角色信息", notes = "根据角色id更新角色的基本信息") @ApiOperation(value = "更新角色信息", notes = "根据角色id更新角色的基本信息")
@ApiImplicitParam(name = "role", value = "角色实体role", required = true, dataType = "RoleVo") @ApiImplicitParam(name = "role", value = "角色实体role", required = true, dataType = "RoleVo")
@Log("修改角色") @Log("修改角色")
...@@ -162,7 +161,7 @@ public class RoleController extends BaseController { ...@@ -162,7 +161,7 @@ public class RoleController extends BaseController {
* @date 2018/9/14 18:23 * @date 2018/9/14 18:23
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('sys:role:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "创建角色", notes = "创建角色") @ApiOperation(value = "创建角色", notes = "创建角色")
@ApiImplicitParam(name = "role", value = "角色实体role", required = true, dataType = "RoleVo") @ApiImplicitParam(name = "role", value = "角色实体role", required = true, dataType = "RoleVo")
@Log("新增角色") @Log("新增角色")
...@@ -180,7 +179,7 @@ public class RoleController extends BaseController { ...@@ -180,7 +179,7 @@ public class RoleController extends BaseController {
* @date 2018/9/14 18:24 * @date 2018/9/14 18:24
*/ */
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
@PreAuthorize("hasAuthority('sys:role:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "删除角色", notes = "根据ID删除角色") @ApiOperation(value = "删除角色", notes = "根据ID删除角色")
@ApiImplicitParam(name = "id", value = "角色ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "角色ID", required = true, paramType = "path")
@Log("删除角色") @Log("删除角色")
...@@ -201,7 +200,7 @@ public class RoleController extends BaseController { ...@@ -201,7 +200,7 @@ public class RoleController extends BaseController {
* @date 2018/12/4 10:00 * @date 2018/12/4 10:00
*/ */
@PostMapping("deleteAll") @PostMapping("deleteAll")
@PreAuthorize("hasAuthority('sys:role:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "批量删除角色", notes = "根据角色id批量删除角色") @ApiOperation(value = "批量删除角色", notes = "根据角色id批量删除角色")
@ApiImplicitParam(name = "ids", value = "角色ID", dataType = "Long") @ApiImplicitParam(name = "ids", value = "角色ID", dataType = "Long")
@Log("批量删除角色") @Log("批量删除角色")
......
...@@ -8,6 +8,7 @@ import com.github.tangyi.common.core.utils.*; ...@@ -8,6 +8,7 @@ import com.github.tangyi.common.core.utils.*;
import com.github.tangyi.common.core.vo.UserVo; import com.github.tangyi.common.core.vo.UserVo;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.annotations.AdminTenantTeacherAuthorization;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.constant.SecurityConstant;
import com.github.tangyi.user.api.dto.UserDto; import com.github.tangyi.user.api.dto.UserDto;
import com.github.tangyi.user.api.dto.UserInfoDto; import com.github.tangyi.user.api.dto.UserInfoDto;
...@@ -26,7 +27,6 @@ import org.apache.commons.lang.ArrayUtils; ...@@ -26,7 +27,6 @@ import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
...@@ -175,7 +175,7 @@ public class UserController extends BaseController { ...@@ -175,7 +175,7 @@ public class UserController extends BaseController {
* @date 2018/8/26 14:34 * @date 2018/8/26 14:34
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('sys:user:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "创建用户", notes = "创建用户") @ApiOperation(value = "创建用户", notes = "创建用户")
@ApiImplicitParam(name = "userDto", value = "用户实体user", required = true, dataType = "UserDto") @ApiImplicitParam(name = "userDto", value = "用户实体user", required = true, dataType = "UserDto")
@Log("新增用户") @Log("新增用户")
...@@ -193,7 +193,7 @@ public class UserController extends BaseController { ...@@ -193,7 +193,7 @@ public class UserController extends BaseController {
* @date 2018/8/26 15:06 * @date 2018/8/26 15:06
*/ */
@PutMapping("/{id:[a-zA-Z0-9,]+}") @PutMapping("/{id:[a-zA-Z0-9,]+}")
@PreAuthorize("hasAuthority('sys:user:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "更新用户信息", notes = "根据用户id更新用户的基本信息、角色信息") @ApiOperation(value = "更新用户信息", notes = "根据用户id更新用户的基本信息、角色信息")
@ApiImplicitParam(name = "userDto", value = "用户实体user", required = true, dataType = "UserDto") @ApiImplicitParam(name = "userDto", value = "用户实体user", required = true, dataType = "UserDto")
@Log("修改用户") @Log("修改用户")
...@@ -266,7 +266,7 @@ public class UserController extends BaseController { ...@@ -266,7 +266,7 @@ public class UserController extends BaseController {
* @date 2018/8/26 15:28 * @date 2018/8/26 15:28
*/ */
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
@PreAuthorize("hasAuthority('sys:user:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "删除用户", notes = "根据ID删除用户") @ApiOperation(value = "删除用户", notes = "根据ID删除用户")
@ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "path")
@Log("删除用户") @Log("删除用户")
...@@ -291,7 +291,7 @@ public class UserController extends BaseController { ...@@ -291,7 +291,7 @@ public class UserController extends BaseController {
* @date 2018/11/26 22:11 * @date 2018/11/26 22:11
*/ */
@PostMapping("export") @PostMapping("export")
@PreAuthorize("hasAuthority('sys:user:export') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "导出用户", notes = "根据用户id导出用户") @ApiOperation(value = "导出用户", notes = "根据用户id导出用户")
@ApiImplicitParam(name = "userVo", value = "用户信息", required = true, dataType = "UserVo") @ApiImplicitParam(name = "userVo", value = "用户信息", required = true, dataType = "UserVo")
@Log("导出用户") @Log("导出用户")
...@@ -339,7 +339,7 @@ public class UserController extends BaseController { ...@@ -339,7 +339,7 @@ public class UserController extends BaseController {
* @date 2018/11/28 12:44 * @date 2018/11/28 12:44
*/ */
@PostMapping("import") @PostMapping("import")
@PreAuthorize("hasAuthority('sys:user:import') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "导入数据", notes = "导入数据") @ApiOperation(value = "导入数据", notes = "导入数据")
@Log("导入用户") @Log("导入用户")
public ResponseBean<Boolean> importUser(@ApiParam(value = "要上传的文件", required = true) MultipartFile file, HttpServletRequest request) { public ResponseBean<Boolean> importUser(@ApiParam(value = "要上传的文件", required = true) MultipartFile file, HttpServletRequest request) {
...@@ -365,7 +365,7 @@ public class UserController extends BaseController { ...@@ -365,7 +365,7 @@ public class UserController extends BaseController {
* @date 2018/12/4 9:58 * @date 2018/12/4 9:58
*/ */
@PostMapping("deleteAll") @PostMapping("deleteAll")
@PreAuthorize("hasAuthority('sys:user:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "批量删除用户", notes = "根据用户id批量删除用户") @ApiOperation(value = "批量删除用户", notes = "根据用户id批量删除用户")
@ApiImplicitParam(name = "ids", value = "用户信息", dataType = "Long") @ApiImplicitParam(name = "ids", value = "用户信息", dataType = "Long")
@Log("批量删除用户") @Log("批量删除用户")
...@@ -460,7 +460,7 @@ public class UserController extends BaseController { ...@@ -460,7 +460,7 @@ public class UserController extends BaseController {
* @date 2019/6/7 12:00 * @date 2019/6/7 12:00
*/ */
@PutMapping("/resetPassword") @PutMapping("/resetPassword")
@PreAuthorize("hasAuthority('sys:user:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @AdminTenantTeacherAuthorization
@ApiOperation(value = "重置密码", notes = "根据用户id重置密码") @ApiOperation(value = "重置密码", notes = "根据用户id重置密码")
@ApiImplicitParam(name = "userDto", value = "用户实体user", required = true, dataType = "UserDto") @ApiImplicitParam(name = "userDto", value = "用户实体user", required = true, dataType = "UserDto")
@Log("重置密码") @Log("重置密码")
......
...@@ -7,6 +7,7 @@ import com.github.tangyi.common.core.service.CrudService; ...@@ -7,6 +7,7 @@ import com.github.tangyi.common.core.service.CrudService;
import com.github.tangyi.common.core.utils.SysUtil; import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.utils.TreeUtil; import com.github.tangyi.common.core.utils.TreeUtil;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.constant.SecurityConstant;
import com.github.tangyi.common.security.enums.Roles;
import com.github.tangyi.common.security.utils.SecurityUtil; import com.github.tangyi.common.security.utils.SecurityUtil;
import com.github.tangyi.user.api.constant.MenuConstant; import com.github.tangyi.user.api.constant.MenuConstant;
import com.github.tangyi.user.api.dto.MenuDto; import com.github.tangyi.user.api.dto.MenuDto;
...@@ -38,322 +39,346 @@ import java.util.stream.Collectors; ...@@ -38,322 +39,346 @@ import java.util.stream.Collectors;
@Service @Service
public class MenuService extends CrudService<MenuMapper, Menu> { public class MenuService extends CrudService<MenuMapper, Menu> {
private final MenuMapper menuMapper; private final MenuMapper menuMapper;
private final RoleMenuService roleMenuService; private final RoleMenuService roleMenuService;
private final SysProperties sysProperties; private final SysProperties sysProperties;
/** /**
* 返回当前用户的树形菜单集合 * 返回当前用户的树形菜单集合
* *
* @return List * @return List
* @author tangyi * @author tangyi
* @date 2019-09-14 14:41 * @date 2019-09-14 14:41
*/ */
public List<MenuDto> findUserMenu() { public List<MenuDto> findUserMenu() {
List<MenuDto> menuDtoList = new ArrayList<>(); List<MenuDto> menuDtoList = new ArrayList<>();
String tenantCode = SysUtil.getTenantCode(), identifier = SysUtil.getUser(); String tenantCode = SysUtil.getTenantCode(), identifier = SysUtil.getUser();
List<Menu> userMenus; List<Menu> userMenus;
// 查询默认租户的菜单 // 查询默认租户的菜单
Menu condition = new Menu(); Menu condition = new Menu();
condition.setTenantCode(SecurityConstant.DEFAULT_TENANT_CODE); condition.setTenantCode(SecurityConstant.DEFAULT_TENANT_CODE);
condition.setApplicationCode(SysUtil.getSysCode()); condition.setApplicationCode(SysUtil.getSysCode());
condition.setType(MenuConstant.MENU_TYPE_MENU); condition.setType(MenuConstant.MENU_TYPE_MENU);
List<Menu> defaultMenus = findAllList(condition); List<Menu> defaultMenus = findAllList(condition);
// 超级管理员 // 超级管理员
if (identifier.equals(sysProperties.getAdminUser())) { if (identifier.equals(sysProperties.getAdminUser())) {
// 获取租户的菜单和默认租户的菜单,最后组装数据,租户的菜单优先 // 获取租户的菜单和默认租户的菜单,最后组装数据,租户的菜单优先
if (SecurityConstant.DEFAULT_TENANT_CODE.equals(tenantCode)) { if (SecurityConstant.DEFAULT_TENANT_CODE.equals(tenantCode)) {
userMenus = defaultMenus; userMenus = defaultMenus;
} else { } else {
// 获取角色的菜单 // 获取角色的菜单
condition.setTenantCode(tenantCode); condition.setTenantCode(tenantCode);
condition.setApplicationCode(SysUtil.getSysCode()); condition.setApplicationCode(SysUtil.getSysCode());
condition.setType(MenuConstant.MENU_TYPE_MENU); condition.setType(MenuConstant.MENU_TYPE_MENU);
List<Menu> tenantMenus = findAllList(condition); List<Menu> tenantMenus = findAllList(condition);
// 组装数据 // 组装数据
userMenus = mergeMenu(defaultMenus, tenantMenus); userMenus = mergeMenu(defaultMenus, tenantMenus);
} }
} else { } else {
List<Role> roleList = SecurityUtil.getCurrentAuthentication().getAuthorities().stream() List<Role> roleList = SecurityUtil.getCurrentAuthentication().getAuthorities().stream()
// 按角色过滤 // 按角色过滤
.filter(authority -> authority.getAuthority() != null && authority.getAuthority() .filter(authority -> authority.getAuthority() != null && authority.getAuthority()
.startsWith("role_")).map(authority -> { .startsWith("ROLE_")).map(authority -> {
Role role = new Role(); Role role = new Role();
role.setRoleCode(authority.getAuthority()); role.setRoleCode(authority.getAuthority());
return role; return role;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
// 根据角色code批量查找菜单 // 根据角色code批量查找菜单
List<Menu> tenantMenus = finMenuByRoleList(roleList, tenantCode); List<Menu> tenantMenus = finMenuByRoleList(roleList, tenantCode);
// 组装数据 // 组装数据
userMenus = mergeMenu(defaultMenus, tenantMenus); userMenus = mergeMenu(getTenantMenus(defaultMenus), tenantMenus);
} }
if (CollectionUtils.isNotEmpty(userMenus)) { if (CollectionUtils.isNotEmpty(userMenus)) {
userMenus.stream() userMenus.stream()
// 菜单类型 // 菜单类型
.filter(menu -> MenuConstant.MENU_TYPE_MENU.equals(menu.getType())) .filter(menu -> MenuConstant.MENU_TYPE_MENU.equals(menu.getType()))
// dto封装 // dto封装
.map(MenuDto::new) .map(MenuDto::new)
// 去重 // 去重
.distinct().forEach(menuDtoList::add); .distinct().forEach(menuDtoList::add);
// 排序、构建树形关系 // 排序、构建树形关系
return TreeUtil.buildTree(CollUtil.sort(menuDtoList, Comparator.comparingInt(MenuDto::getSort)), CommonConstant.ROOT); return TreeUtil.buildTree(CollUtil.sort(menuDtoList, Comparator.comparingInt(MenuDto::getSort)),
} CommonConstant.ROOT);
return Lists.newArrayList(); }
} return Lists.newArrayList();
}
/** /**
* 根据角色查找菜单 * 根据角色查找菜单
* *
* @param role 角色标识 * @param role 角色标识
* @param tenantCode 租户标识 * @param tenantCode 租户标识
* @return List * @return List
* @author tangyi * @author tangyi
* @date 2018/8/27 16:00 * @date 2018/8/27 16:00
*/ */
@Cacheable(value = "menu#" + CommonConstant.CACHE_EXPIRE, key = "#role") @Cacheable(value = "menu#" + CommonConstant.CACHE_EXPIRE, key = "#role")
public List<Menu> findMenuByRole(String role, String tenantCode) { public List<Menu> findMenuByRole(String role, String tenantCode) {
List<Menu> menus = new ArrayList<>(); List<Menu> menus = new ArrayList<>();
// 返回默认租户的角色菜单 // 返回默认租户的角色菜单
if (!tenantCode.equals(SecurityConstant.DEFAULT_TENANT_CODE)) if (!tenantCode.equals(SecurityConstant.DEFAULT_TENANT_CODE))
menus = menuMapper.findByRole(role, SecurityConstant.DEFAULT_TENANT_CODE); menus = menuMapper.findByRole(role, SecurityConstant.DEFAULT_TENANT_CODE);
List<Menu> tenantMenus = menuMapper.findByRole(role, tenantCode); List<Menu> tenantMenus = menuMapper.findByRole(role, tenantCode);
if (CollectionUtils.isNotEmpty(tenantMenus)) if (CollectionUtils.isNotEmpty(tenantMenus))
menus.addAll(tenantMenus); menus.addAll(tenantMenus);
return menus; return menus;
} }
/** /**
* 批量查询菜单 * 批量查询菜单
* *
* @param roleList roleList * @param roleList roleList
* @param tenantCode tenantCode * @param tenantCode tenantCode
* @return List * @return List
* @author tangyi * @author tangyi
* @date 2019/07/03 23:50:35 * @date 2019/07/03 23:50:35
*/ */
private List<Menu> finMenuByRoleList(List<Role> roleList, String tenantCode) { private List<Menu> finMenuByRoleList(List<Role> roleList, String tenantCode) {
List<Menu> menus = Lists.newArrayList(); List<Menu> menus = Lists.newArrayList();
for (Role role : roleList) { for (Role role : roleList) {
List<Menu> roleMenus = this.findMenuByRole(role.getRoleCode(), tenantCode); List<Menu> roleMenus = this.findMenuByRole(role.getRoleCode(), tenantCode);
if (CollectionUtils.isNotEmpty(roleMenus)) if (CollectionUtils.isNotEmpty(roleMenus))
menus.addAll(roleMenus); menus.addAll(roleMenus);
} }
return menus; return menus;
} }
/** /**
* 查询全部菜单,包括租户本身的菜单和默认租户的菜单 * 查询全部菜单,包括租户本身的菜单和默认租户的菜单
* *
* @param menu menu * @param menu menu
* @return List * @return List
* @author tangyi * @author tangyi
* @date 2019/04/10 17:58 * @date 2019/04/10 17:58
*/ */
@Override @Override
public List<Menu> findAllList(Menu menu) { public List<Menu> findAllList(Menu menu) {
List<Menu> menus = new ArrayList<>(); List<Menu> menus = new ArrayList<>();
if (!menu.getTenantCode().equals(SecurityConstant.DEFAULT_TENANT_CODE)) { if (!menu.getTenantCode().equals(SecurityConstant.DEFAULT_TENANT_CODE)) {
Menu defaultMenu = new Menu(); Menu defaultMenu = new Menu();
defaultMenu.setApplicationCode(SysUtil.getSysCode()); defaultMenu.setApplicationCode(SysUtil.getSysCode());
defaultMenu.setTenantCode(SecurityConstant.DEFAULT_TENANT_CODE); defaultMenu.setTenantCode(SecurityConstant.DEFAULT_TENANT_CODE);
menus = menuMapper.findAllList(defaultMenu); menus = menuMapper.findAllList(defaultMenu);
} }
List<Menu> tenantMenus = menuMapper.findAllList(menu); List<Menu> tenantMenus = menuMapper.findAllList(menu);
if (CollectionUtils.isNotEmpty(tenantMenus)) if (CollectionUtils.isNotEmpty(tenantMenus))
menus = mergeMenu(menus, tenantMenus); menus = mergeMenu(menus, tenantMenus);
return menus; return menus;
} }
/** /**
* 新增菜单 * 新增菜单
* *
* @param menu menu * @param menu menu
* @return int * @return int
* @author tangyi * @author tangyi
* @date 2018/10/28 15:56 * @date 2018/10/28 15:56
*/ */
@Transactional @Transactional
@Override @Override
@CacheEvict(value = {"menu", "user"}, allEntries = true) @CacheEvict(value = {"menu", "user"}, allEntries = true)
public int insert(Menu menu) { public int insert(Menu menu) {
return super.insert(menu); return super.insert(menu);
} }
/** /**
* 更新菜单,区分租户本身的菜单和默认租户的菜单 * 更新菜单,区分租户本身的菜单和默认租户的菜单
* *
* @param menu menu * @param menu menu
* @return int * @return int
* @author tangyi * @author tangyi
* @date 2018/10/30 20:19 * @date 2018/10/30 20:19
*/ */
@Transactional @Transactional
@Override @Override
@CacheEvict(value = {"menu", "user"}, allEntries = true) @CacheEvict(value = {"menu", "user"}, allEntries = true)
public int update(Menu menu) { public int update(Menu menu) {
String userCode = SysUtil.getUser(); String userCode = SysUtil.getUser();
String sysCode = SysUtil.getSysCode(); String sysCode = SysUtil.getSysCode();
String tenantCode = SysUtil.getTenantCode(); String tenantCode = SysUtil.getTenantCode();
menu = this.get(menu); menu = this.get(menu);
// 默认租户的用户更新菜单或更新本租户的菜单,直接更新 // 默认租户的用户更新菜单或更新本租户的菜单,直接更新
if (tenantCode.equals(SecurityConstant.DEFAULT_TENANT_CODE) || tenantCode.equals(menu.getTenantCode())) { if (tenantCode.equals(SecurityConstant.DEFAULT_TENANT_CODE) || tenantCode.equals(menu.getTenantCode())) {
return super.update(menu); return super.update(menu);
} else { } else {
// 其它租户更新默认租户的菜单,copy一份原始菜单的数据 // 其它租户更新默认租户的菜单,copy一份原始菜单的数据
Long originalId = menu.getId(); Long originalId = menu.getId();
String originalTenantCode = menu.getTenantCode(); String originalTenantCode = menu.getTenantCode();
// 重新初始化ID // 重新初始化ID
menu.setId(null); menu.setId(null);
menu.setCommonValue(userCode, sysCode, tenantCode); menu.setCommonValue(userCode, sysCode, tenantCode);
this.insert(menu); this.insert(menu);
// copy子菜单 // copy子菜单
Long newMenuId = menu.getId(); Long newMenuId = menu.getId();
Menu condition = new Menu(); Menu condition = new Menu();
condition.setParentId(originalId); condition.setParentId(originalId);
condition.setTenantCode(originalTenantCode); condition.setTenantCode(originalTenantCode);
// 查询子菜单 // 查询子菜单
List<Menu> childrenMenus = findList(condition); List<Menu> childrenMenus = findList(condition);
// 子菜单ID列表 // 子菜单ID列表
List<Long> childrenMenuIds = new ArrayList<>(); List<Long> childrenMenuIds = new ArrayList<>();
if (CollectionUtils.isNotEmpty(childrenMenus)) { if (CollectionUtils.isNotEmpty(childrenMenus)) {
childrenMenus.forEach(children -> { childrenMenus.forEach(children -> {
childrenMenuIds.add(children.getId()); childrenMenuIds.add(children.getId());
// 重新初始化ID // 重新初始化ID
children.setId(null); children.setId(null);
children.setCommonValue(userCode, sysCode, tenantCode); children.setCommonValue(userCode, sysCode, tenantCode);
// 重新绑定父菜单 // 重新绑定父菜单
children.setParentId(newMenuId); children.setParentId(newMenuId);
}); });
// 批量插入 // 批量插入
insertBatch(childrenMenus); insertBatch(childrenMenus);
} }
// 更新权限数据roleMenu // 更新权限数据roleMenu
updateRoleMenu(originalId, childrenMenuIds, userCode, sysCode, tenantCode); updateRoleMenu(originalId, childrenMenuIds, userCode, sysCode, tenantCode);
} }
return super.update(menu); return super.update(menu);
} }
/** /**
* 删除菜单 * 删除菜单
* *
* @param menu menu * @param menu menu
* @return int * @return int
* @author tangyi * @author tangyi
* @date 2018/8/27 16:22 * @date 2018/8/27 16:22
*/ */
@Override @Override
@Transactional @Transactional
@CacheEvict(value = {"menu", "user"}, allEntries = true) @CacheEvict(value = {"menu", "user"}, allEntries = true)
public int delete(Menu menu) { public int delete(Menu menu) {
// 删除当前菜单 // 删除当前菜单
super.delete(menu); super.delete(menu);
// 删除父节点为当前节点的菜单 // 删除父节点为当前节点的菜单
Menu parentMenu = new Menu(); Menu parentMenu = new Menu();
parentMenu.setParentId(menu.getId()); parentMenu.setParentId(menu.getId());
parentMenu.setNewRecord(false); parentMenu.setNewRecord(false);
parentMenu.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode()); parentMenu.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
parentMenu.setDelFlag(CommonConstant.DEL_FLAG_DEL); parentMenu.setDelFlag(CommonConstant.DEL_FLAG_DEL);
return super.update(parentMenu); return super.update(parentMenu);
} }
/** /**
* 批量插入 * 批量插入
* *
* @param menus menus * @param menus menus
* @return int * @return int
* @author tangyi * @author tangyi
* @date 2019-09-03 12:19 * @date 2019-09-03 12:19
*/ */
@Transactional @Transactional
public int insertBatch(List<Menu> menus) { public int insertBatch(List<Menu> menus) {
return dao.insertBatch(menus); return dao.insertBatch(menus);
} }
/** /**
* 合并默认租户和租户的菜单,租户菜单优先 * 合并默认租户和租户的菜单,租户菜单优先
* *
* @param defaultMenus defaultMenus * @param defaultMenus defaultMenus
* @param tenantMenus tenantMenus * @param tenantMenus tenantMenus
* @return List * @return List
* @author tangyi * @author tangyi
* @date 2019-09-14 14:45 * @date 2019-09-14 14:45
*/ */
private List<Menu> mergeMenu(List<Menu> defaultMenus, List<Menu> tenantMenus) { private List<Menu> mergeMenu(List<Menu> defaultMenus, List<Menu> tenantMenus) {
if (CollectionUtils.isEmpty(tenantMenus)) if (CollectionUtils.isEmpty(tenantMenus))
return defaultMenus; return defaultMenus;
List<Menu> userMenus = new ArrayList<>(); List<Menu> userMenus = new ArrayList<>();
// 默认菜单 // 默认菜单
defaultMenus.forEach(defaultMenu -> { defaultMenus.forEach(defaultMenu -> {
Optional<Menu> menu = tenantMenus.stream() Optional<Menu> menu = tenantMenus.stream()
.filter(tenantMenu -> tenantMenu.getName().equals(defaultMenu.getName())).findFirst(); .filter(tenantMenu -> tenantMenu.getName().equals(defaultMenu.getName())).findFirst();
if (menu.isPresent()) { if (menu.isPresent()) {
userMenus.add(menu.get()); userMenus.add(menu.get());
} else { } else {
userMenus.add(defaultMenu); userMenus.add(defaultMenu);
} }
}); });
// 租户菜单 // 租户菜单
tenantMenus.forEach(tenantMenu -> { tenantMenus.forEach(tenantMenu -> {
Optional<Menu> exist = userMenus.stream() Optional<Menu> exist = userMenus.stream()
.filter(userMenu -> userMenu.getName().equals(tenantMenu.getName()) && userMenu.getParentId().equals(tenantMenu.getParentId())).findFirst(); .filter(userMenu -> userMenu.getName().equals(tenantMenu.getName()) && userMenu.getParentId()
if (!exist.isPresent()) { .equals(tenantMenu.getParentId())).findFirst();
userMenus.add(tenantMenu); if (!exist.isPresent()) {
} userMenus.add(tenantMenu);
}); }
return userMenus; });
} return userMenus;
}
/** /**
* 更新权限数据 * 更新权限数据
* *
* @param menuId menuId * @param menuId menuId
* @param childrenMenuIds childrenMenuIds * @param childrenMenuIds childrenMenuIds
* @param userCode userCode * @param userCode userCode
* @param sysCode sysCode * @param sysCode sysCode
* @param tenantCode tenantCode * @param tenantCode tenantCode
* @return * @return
* @author tangyi * @author tangyi
* @date 2019-09-14 15:57 * @date 2019-09-14 15:57
*/ */
@Transactional @Transactional
public void updateRoleMenu(Long menuId, List<Long> childrenMenuIds, String userCode, String sysCode, public void updateRoleMenu(Long menuId, List<Long> childrenMenuIds, String userCode, String sysCode,
String tenantCode) { String tenantCode) {
List<RoleMenu> condition = new ArrayList<>(); List<RoleMenu> condition = new ArrayList<>();
RoleMenu roleMenu = new RoleMenu(); RoleMenu roleMenu = new RoleMenu();
roleMenu.setMenuId(menuId); roleMenu.setMenuId(menuId);
// 主菜单 // 主菜单
condition.add(roleMenu); condition.add(roleMenu);
// 子菜单 // 子菜单
if (CollectionUtils.isNotEmpty(childrenMenuIds)) { if (CollectionUtils.isNotEmpty(childrenMenuIds)) {
childrenMenuIds.forEach(childrenMenuId -> { childrenMenuIds.forEach(childrenMenuId -> {
RoleMenu childRoleMenu = new RoleMenu(); RoleMenu childRoleMenu = new RoleMenu();
childRoleMenu.setMenuId(childrenMenuId); childRoleMenu.setMenuId(childrenMenuId);
condition.add(childRoleMenu); condition.add(childRoleMenu);
}); });
} }
// 查询 // 查询
List<RoleMenu> roleMenus = roleMenuService.getByMenuIds(condition); List<RoleMenu> roleMenus = roleMenuService.getByMenuIds(condition);
if (CollectionUtils.isNotEmpty(roleMenus)) { if (CollectionUtils.isNotEmpty(roleMenus)) {
roleMenus.forEach(tempRoleMenu -> { roleMenus.forEach(tempRoleMenu -> {
// 重新初始化ID // 重新初始化ID
tempRoleMenu.setId(null); tempRoleMenu.setId(null);
tempRoleMenu.setCommonValue(userCode, sysCode, tenantCode); tempRoleMenu.setCommonValue(userCode, sysCode, tenantCode);
}); });
// 批量插入 // 批量插入
roleMenuService.insertBatch(roleMenus); roleMenuService.insertBatch(roleMenus);
} }
} }
/** /**
* 根据租户code删除 * 根据租户code删除
* @param menu menu *
* @return int * @param menu menu
*/ * @return int
@Transactional */
public int deleteByTenantCode(Menu menu) { @Transactional
return this.dao.deleteByTenantCode(menu); public int deleteByTenantCode(Menu menu) {
} return this.dao.deleteByTenantCode(menu);
}
/**
* 获取租户权限的菜单
* @param defaultMenus defaultMenus
* @return List
*/
private List<Menu> getTenantMenus(List<Menu> defaultMenus) {
List<Menu> tenantMenus = new ArrayList<>();
if (CollectionUtils.isNotEmpty(defaultMenus)) {
defaultMenus.forEach(menu -> {
String permission = menu.getPermission();
// 过滤客户端管理、路由管理、系统监控菜单
if (!permission.equals(MenuConstant.MENU_CLIENT) && !permission.equals(MenuConstant.MENU_ROUTE)
&& !permission.equals(MenuConstant.MENU_TENANT) && !permission
.equals(MenuConstant.MENU_MONITOR)) {
tenantMenus.add(menu);
}
});
}
return tenantMenus;
}
} }
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
<okhttp.version>3.8.1</okhttp.version> <okhttp.version>3.8.1</okhttp.version>
<aliyun.version>4.0.3</aliyun.version> <aliyun.version>4.0.3</aliyun.version>
<weixin.version>3.4.0</weixin.version> <weixin.version>3.4.0</weixin.version>
<jjwt.version>0.9.0</jjwt.version>
<!-- docker --> <!-- docker -->
<docker.maven.verion>1.4.3</docker.maven.verion> <docker.maven.verion>1.4.3</docker.maven.verion>
...@@ -301,6 +302,13 @@ ...@@ -301,6 +302,13 @@
<artifactId>weixin-java-pay</artifactId> <artifactId>weixin-java-pay</artifactId>
<version>${weixin.version}</version> <version>${weixin.version}</version>
</dependency> </dependency>
<!-- jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
......
Markdown is supported
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