sentinel
This commit is contained in:
parent
fff8fb7d86
commit
46eb9a0303
|
|
@ -23,6 +23,13 @@
|
||||||
<artifactId>ruoyi-common-core</artifactId>
|
<artifactId>ruoyi-common-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- spring-security-core -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-core</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package com.ruoyi.system.api;
|
package com.ruoyi.system.api;
|
||||||
|
|
||||||
|
import com.ruoyi.system.api.model.RoleAndPermission;
|
||||||
|
import com.ruoyi.system.api.model.UserInfo;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
|
@ -8,6 +10,8 @@ import com.ruoyi.common.core.domain.R;
|
||||||
import com.ruoyi.system.api.factory.RemoteUserFallbackFactory;
|
import com.ruoyi.system.api.factory.RemoteUserFallbackFactory;
|
||||||
import com.ruoyi.system.api.model.LoginUser;
|
import com.ruoyi.system.api.model.LoginUser;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户服务
|
* 用户服务
|
||||||
*
|
*
|
||||||
|
|
@ -23,5 +27,34 @@ public interface RemoteUserService
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@GetMapping(value = "/user/info/{username}")
|
@GetMapping(value = "/user/info/{username}")
|
||||||
public R<LoginUser> getUserInfo(@PathVariable("username") String username);
|
public R<UserInfo> getUserInfo(@PathVariable("username") String username);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据用户id查询角色
|
||||||
|
*
|
||||||
|
* @param userId 用户名
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "/user/roles/{userId}")
|
||||||
|
public R<Set<String>> getRoles(@PathVariable("userId") Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据用户id查询权限
|
||||||
|
* @param userId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "/user/permissions/{userId}")
|
||||||
|
public R<Set<String>> getPermissions(@PathVariable("userId") Long userId);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据用户id查询角色和权限
|
||||||
|
*
|
||||||
|
* @param userId 用户名
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "/user/rolesAndPermissions/{userId}")
|
||||||
|
public R<RoleAndPermission> getRolesAndPermissions(@PathVariable("userId") Long userId);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package com.ruoyi.system.api.factory;
|
package com.ruoyi.system.api.factory;
|
||||||
|
|
||||||
|
import com.ruoyi.system.api.model.RoleAndPermission;
|
||||||
|
import com.ruoyi.system.api.model.UserInfo;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
@ -8,6 +10,8 @@ import com.ruoyi.system.api.RemoteUserService;
|
||||||
import com.ruoyi.system.api.model.LoginUser;
|
import com.ruoyi.system.api.model.LoginUser;
|
||||||
import feign.hystrix.FallbackFactory;
|
import feign.hystrix.FallbackFactory;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户服务降级处理
|
* 用户服务降级处理
|
||||||
*
|
*
|
||||||
|
|
@ -25,10 +29,25 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
|
||||||
return new RemoteUserService()
|
return new RemoteUserService()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public R<LoginUser> getUserInfo(String username)
|
public R<UserInfo> getUserInfo(String username)
|
||||||
{
|
{
|
||||||
return R.fail("获取用户失败:" + throwable.getMessage());
|
return R.fail("获取用户失败:" + throwable.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public R<Set<String>> getRoles(Long userId) {
|
||||||
|
return R.fail("获取用户角色失败:" + throwable.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public R<Set<String>> getPermissions(Long userId) {
|
||||||
|
return R.fail("获取用户权限失败:" + throwable.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public R<RoleAndPermission> getRolesAndPermissions(Long userId) {
|
||||||
|
return R.fail("获取用户角色和权限失败:" + throwable.getMessage());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,28 @@
|
||||||
package com.ruoyi.system.api.model;
|
package com.ruoyi.system.api.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Set;
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import com.ruoyi.system.api.domain.SysUser;
|
import com.ruoyi.system.api.domain.SysUser;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.security.core.CredentialsContainer;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户信息
|
* 用户信息
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
public class LoginUser implements Serializable
|
@Slf4j
|
||||||
|
public class LoginUser implements Serializable, UserDetails,CredentialsContainer
|
||||||
{
|
{
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|
@ -21,7 +34,7 @@ public class LoginUser implements Serializable
|
||||||
/**
|
/**
|
||||||
* 用户名id
|
* 用户名id
|
||||||
*/
|
*/
|
||||||
private Long userid;
|
private Long userId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户名
|
* 用户名
|
||||||
|
|
@ -58,6 +71,63 @@ public class LoginUser implements Serializable
|
||||||
*/
|
*/
|
||||||
private SysUser sysUser;
|
private SysUser sysUser;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private Set<GrantedAuthority> authorities;
|
||||||
|
|
||||||
|
private boolean accountNonExpired;
|
||||||
|
|
||||||
|
private boolean accountNonLocked;
|
||||||
|
|
||||||
|
private boolean credentialsNonExpired;
|
||||||
|
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
|
public LoginUser() {
|
||||||
|
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
this.accountNonExpired = accountNonExpired;
|
||||||
|
this.credentialsNonExpired = credentialsNonExpired;
|
||||||
|
this.accountNonLocked = accountNonLocked;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthorities(Set<GrantedAuthority> authorities) {
|
||||||
|
this.authorities = authorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser(Long userid, String username, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
this.accountNonExpired = accountNonExpired;
|
||||||
|
this.credentialsNonExpired = credentialsNonExpired;
|
||||||
|
this.accountNonLocked = accountNonLocked;
|
||||||
|
this.username = username;
|
||||||
|
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
|
||||||
|
this.userId = userid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser(Long userid, String username,String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
this.accountNonExpired = accountNonExpired;
|
||||||
|
this.credentialsNonExpired = credentialsNonExpired;
|
||||||
|
this.accountNonLocked = accountNonLocked;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
|
||||||
|
this.userId = userid;
|
||||||
|
}
|
||||||
|
|
||||||
public String getToken()
|
public String getToken()
|
||||||
{
|
{
|
||||||
return token;
|
return token;
|
||||||
|
|
@ -68,16 +138,17 @@ public class LoginUser implements Serializable
|
||||||
this.token = token;
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getUserid()
|
public Long getUserId()
|
||||||
{
|
{
|
||||||
return userid;
|
return userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUserid(Long userid)
|
public void setUserId(Long userId)
|
||||||
{
|
{
|
||||||
this.userid = userid;
|
this.userId = userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getUsername()
|
public String getUsername()
|
||||||
{
|
{
|
||||||
return username;
|
return username;
|
||||||
|
|
@ -147,4 +218,221 @@ public class LoginUser implements Serializable
|
||||||
{
|
{
|
||||||
this.sysUser = sysUser;
|
this.sysUser = sysUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<GrantedAuthority> getAuthorities() {
|
||||||
|
return this.authorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return this.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonExpired() {
|
||||||
|
return this.accountNonExpired;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonLocked() {
|
||||||
|
return this.accountNonLocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCredentialsNonExpired() {
|
||||||
|
return this.credentialsNonExpired;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eraseCredentials() {
|
||||||
|
this.password = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SortedSet<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) {
|
||||||
|
Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
|
||||||
|
SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet(new LoginUser.AuthorityComparator());
|
||||||
|
Iterator var2 = authorities.iterator();
|
||||||
|
|
||||||
|
while(var2.hasNext()) {
|
||||||
|
GrantedAuthority grantedAuthority = (GrantedAuthority)var2.next();
|
||||||
|
Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements");
|
||||||
|
sortedAuthorities.add(grantedAuthority);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortedAuthorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object rhs) {
|
||||||
|
return rhs instanceof LoginUser ? this.username.equals(((LoginUser)rhs).username) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.username.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(super.toString()).append(": ");
|
||||||
|
sb.append("Username: ").append(this.username).append("; ");
|
||||||
|
sb.append("Password: [PROTECTED]; ");
|
||||||
|
sb.append("Enabled: ").append(this.enabled).append("; ");
|
||||||
|
sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; ");
|
||||||
|
sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; ");
|
||||||
|
sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; ");
|
||||||
|
if (!this.authorities.isEmpty()) {
|
||||||
|
sb.append("Granted Authorities: ");
|
||||||
|
boolean first = true;
|
||||||
|
Iterator var3 = this.authorities.iterator();
|
||||||
|
|
||||||
|
while(var3.hasNext()) {
|
||||||
|
GrantedAuthority auth = (GrantedAuthority)var3.next();
|
||||||
|
if (!first) {
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
sb.append(auth);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append("Not granted any authorities");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LoginUser.UserBuilder withUsername(String username) {
|
||||||
|
return builder().username(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LoginUser.UserBuilder builder() {
|
||||||
|
return new LoginUser.UserBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @deprecated */
|
||||||
|
@Deprecated
|
||||||
|
public static LoginUser.UserBuilder withDefaultPasswordEncoder() {
|
||||||
|
log.warn("User.withDefaultPasswordEncoder() is considered unsafe for production and is only intended for sample applications.");
|
||||||
|
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||||
|
LoginUser.UserBuilder var10000 = builder();
|
||||||
|
encoder.getClass();
|
||||||
|
return var10000.passwordEncoder(encoder::encode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LoginUser.UserBuilder withUserDetails(UserDetails userDetails) {
|
||||||
|
return withUsername(userDetails.getUsername()).password(userDetails.getPassword()).accountExpired(!userDetails.isAccountNonExpired()).accountLocked(!userDetails.isAccountNonLocked()).authorities(userDetails.getAuthorities()).credentialsExpired(!userDetails.isCredentialsNonExpired()).disabled(!userDetails.isEnabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class UserBuilder {
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private List<GrantedAuthority> authorities;
|
||||||
|
private boolean accountExpired;
|
||||||
|
private boolean accountLocked;
|
||||||
|
private boolean credentialsExpired;
|
||||||
|
private boolean disabled;
|
||||||
|
private Function<String, String> passwordEncoder;
|
||||||
|
|
||||||
|
private UserBuilder() {
|
||||||
|
this.passwordEncoder = (password) -> {
|
||||||
|
return password;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser.UserBuilder username(String username) {
|
||||||
|
Assert.notNull(username, "username cannot be null");
|
||||||
|
this.username = username;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser.UserBuilder password(String password) {
|
||||||
|
Assert.notNull(password, "password cannot be null");
|
||||||
|
this.password = password;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser.UserBuilder passwordEncoder(Function<String, String> encoder) {
|
||||||
|
Assert.notNull(encoder, "encoder cannot be null");
|
||||||
|
this.passwordEncoder = encoder;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser.UserBuilder roles(String... roles) {
|
||||||
|
List<GrantedAuthority> authorities = new ArrayList(roles.length);
|
||||||
|
String[] var3 = roles;
|
||||||
|
int var4 = roles.length;
|
||||||
|
|
||||||
|
for(int var5 = 0; var5 < var4; ++var5) {
|
||||||
|
String role = var3[var5];
|
||||||
|
Assert.isTrue(!role.startsWith("ROLE_"), () -> {
|
||||||
|
return role + " cannot start with ROLE_ (it is automatically added)";
|
||||||
|
});
|
||||||
|
authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.authorities((Collection)authorities);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser.UserBuilder authorities(GrantedAuthority... authorities) {
|
||||||
|
return this.authorities((Collection)Arrays.asList(authorities));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser.UserBuilder authorities(Collection<? extends GrantedAuthority> authorities) {
|
||||||
|
this.authorities = new ArrayList(authorities);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser.UserBuilder authorities(String... authorities) {
|
||||||
|
return this.authorities((Collection) AuthorityUtils.createAuthorityList(authorities));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser.UserBuilder accountExpired(boolean accountExpired) {
|
||||||
|
this.accountExpired = accountExpired;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser.UserBuilder accountLocked(boolean accountLocked) {
|
||||||
|
this.accountLocked = accountLocked;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser.UserBuilder credentialsExpired(boolean credentialsExpired) {
|
||||||
|
this.credentialsExpired = credentialsExpired;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser.UserBuilder disabled(boolean disabled) {
|
||||||
|
this.disabled = disabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserDetails build() {
|
||||||
|
String encodedPassword = (String)this.passwordEncoder.apply(this.password);
|
||||||
|
return new User(this.username, encodedPassword, !this.disabled, !this.accountExpired, !this.credentialsExpired, !this.accountLocked, this.authorities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AuthorityComparator implements Comparator<GrantedAuthority>, Serializable {
|
||||||
|
private static final long serialVersionUID = 530L;
|
||||||
|
|
||||||
|
private AuthorityComparator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(GrantedAuthority g1, GrantedAuthority g2) {
|
||||||
|
if (g2.getAuthority() == null) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return g1.getAuthority() == null ? 1 : g1.getAuthority().compareTo(g2.getAuthority());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.ruoyi.system.api.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色表 sys_role
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RoleAndPermission implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色集合
|
||||||
|
*/
|
||||||
|
private Set<String> roles ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限集合
|
||||||
|
*/
|
||||||
|
private Set<String> permissions ;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package com.ruoyi.system.api.model;
|
||||||
|
|
||||||
|
import com.ruoyi.system.api.domain.SysUser;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户信息
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class UserInfo implements Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户基本信息
|
||||||
|
*/
|
||||||
|
private SysUser sysUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限标识集合
|
||||||
|
*/
|
||||||
|
private Set<String> permissions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色集合
|
||||||
|
*/
|
||||||
|
private Set<String> roles;
|
||||||
|
|
||||||
|
public SysUser getSysUser()
|
||||||
|
{
|
||||||
|
return sysUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSysUser(SysUser sysUser)
|
||||||
|
{
|
||||||
|
this.sysUser = sysUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getPermissions()
|
||||||
|
{
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermissions(Set<String> permissions)
|
||||||
|
{
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getRoles()
|
||||||
|
{
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoles(Set<String> roles)
|
||||||
|
{
|
||||||
|
this.roles = roles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
package com.ruoyi.auth.config;
|
||||||
|
|
||||||
|
import com.ruoyi.auth.exception.CustomWebResponseExceptionTranslator;
|
||||||
|
import com.ruoyi.common.core.constant.CacheConstants;
|
||||||
|
import com.ruoyi.common.core.constant.SecurityConstants;
|
||||||
|
import com.ruoyi.common.security.service.RedisClientDetailsService;
|
||||||
|
import com.ruoyi.system.api.model.LoginUser;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
|
||||||
|
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.EnableAuthorizationServer;
|
||||||
|
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.provider.token.TokenEnhancer;
|
||||||
|
import org.springframework.security.oauth2.provider.token.TokenStore;
|
||||||
|
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth2 认证服务配置
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableAuthorizationServer
|
||||||
|
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DataSource dataSource;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisConnectionFactory redisConnectionFactory;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserDetailsService userDetailsService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TokenEnhancer tokenEnhancer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义授权和令牌端点以及令牌服务
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
|
||||||
|
{
|
||||||
|
endpoints
|
||||||
|
// 请求方式
|
||||||
|
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
|
||||||
|
// 指定token存储位置
|
||||||
|
.tokenStore(tokenStore())
|
||||||
|
// 自定义生成令牌
|
||||||
|
.tokenEnhancer(tokenEnhancer)
|
||||||
|
// 用户账号密码认证
|
||||||
|
.userDetailsService(userDetailsService)
|
||||||
|
// 指定认证管理器
|
||||||
|
.authenticationManager(authenticationManager)
|
||||||
|
// 是否重复使用 refresh_token
|
||||||
|
.reuseRefreshTokens(false)
|
||||||
|
// 自定义异常处理
|
||||||
|
.exceptionTranslator(new CustomWebResponseExceptionTranslator());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置令牌端点(Token Endpoint)的安全约束
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
|
||||||
|
{
|
||||||
|
oauthServer.allowFormAuthenticationForClients().checkTokenAccess("permitAll()");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 声明 ClientDetails实现
|
||||||
|
*/
|
||||||
|
public RedisClientDetailsService clientDetailsService()
|
||||||
|
{
|
||||||
|
RedisClientDetailsService clientDetailsService = new RedisClientDetailsService(dataSource);
|
||||||
|
return clientDetailsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置客户端详情
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
|
||||||
|
{
|
||||||
|
clients.withClientDetails(clientDetailsService());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于 Redis 实现,令牌保存到缓存
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public TokenStore tokenStore()
|
||||||
|
{
|
||||||
|
RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
|
||||||
|
tokenStore.setPrefix(CacheConstants.OAUTH_ACCESS);
|
||||||
|
return tokenStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义生成令牌
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public TokenEnhancer tokenEnhancer()
|
||||||
|
{
|
||||||
|
return (accessToken, authentication) -> {
|
||||||
|
if (authentication.getUserAuthentication() != null)
|
||||||
|
{
|
||||||
|
Map<String, Object> additionalInformation = new LinkedHashMap<String, Object>();
|
||||||
|
LoginUser user = (LoginUser) authentication.getUserAuthentication().getPrincipal();
|
||||||
|
additionalInformation.put(SecurityConstants.DETAILS_USER_ID, user.getUserId());
|
||||||
|
additionalInformation.put(SecurityConstants.DETAILS_USERNAME, user.getUsername());
|
||||||
|
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation);
|
||||||
|
}
|
||||||
|
return accessToken;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package com.ruoyi.auth.config;
|
||||||
|
|
||||||
|
import com.ruoyi.common.security.service.UserDetailsServiceImpl;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
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.password.PasswordEncoder;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Security 安全认证相关配置
|
||||||
|
* Oauth2依赖于Security 默认情况下WebSecurityConfig执行比ResourceServerConfig优先
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Order(99)
|
||||||
|
@Configuration
|
||||||
|
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
|
||||||
|
{
|
||||||
|
// @Resource(name= "defaultUserDetailsService")
|
||||||
|
// private UserDetailsService userDetailsService;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder()
|
||||||
|
{
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Override
|
||||||
|
public AuthenticationManager authenticationManagerBean() throws Exception
|
||||||
|
{
|
||||||
|
return super.authenticationManagerBean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(AuthenticationManagerBuilder auth) throws Exception
|
||||||
|
{
|
||||||
|
auth.userDetailsService(getUserDetailsService()).passwordEncoder(passwordEncoder());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception
|
||||||
|
{
|
||||||
|
http
|
||||||
|
.authorizeRequests()
|
||||||
|
.antMatchers(
|
||||||
|
"/actuator/**",
|
||||||
|
"/oauth/*",
|
||||||
|
"/token/**",
|
||||||
|
"/logout",
|
||||||
|
"/login"
|
||||||
|
).permitAll()
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
.and().csrf().disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public UserDetailsService getUserDetailsService() {
|
||||||
|
return new UserDetailsServiceImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package com.ruoyi.auth.controller;
|
package com.ruoyi.auth.controller;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import com.ruoyi.system.api.model.UserInfo;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
@ -27,16 +29,16 @@ public class TokenController
|
||||||
@Autowired
|
@Autowired
|
||||||
private SysLoginService sysLoginService;
|
private SysLoginService sysLoginService;
|
||||||
|
|
||||||
@PostMapping("login")
|
// @PostMapping("login")
|
||||||
public R<?> login(@RequestBody LoginBody form)
|
// public R<?> login(@RequestBody LoginBody form)
|
||||||
{
|
// {
|
||||||
// 用户登录
|
// // 用户登录
|
||||||
LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword());
|
// UserInfo userInfo = sysLoginService.login(form.getUsername(), form.getPassword());
|
||||||
// 获取登录token
|
// // 获取登录token
|
||||||
return R.ok(tokenService.createToken(userInfo));
|
// return R.ok(tokenService.createToken(userInfo));
|
||||||
}
|
// }
|
||||||
|
|
||||||
@DeleteMapping("logout")
|
@DeleteMapping("token/logout")
|
||||||
public R<?> logout(HttpServletRequest request)
|
public R<?> logout(HttpServletRequest request)
|
||||||
{
|
{
|
||||||
LoginUser loginUser = tokenService.getLoginUser(request);
|
LoginUser loginUser = tokenService.getLoginUser(request);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.ruoyi.auth.controller;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.security.Principal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 身份信息获取
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/oauth")
|
||||||
|
public class UserController
|
||||||
|
{
|
||||||
|
@RequestMapping("/user")
|
||||||
|
public Principal user(Principal user)
|
||||||
|
{
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.ruoyi.auth.exception;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oauth2自定义异常
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
**/
|
||||||
|
@JsonSerialize(using = CustomOauthExceptionSerializer.class)
|
||||||
|
public class CustomOauthException extends OAuth2Exception
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public CustomOauthException(String msg)
|
||||||
|
{
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.ruoyi.auth.exception;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||||
|
import com.ruoyi.common.core.constant.HttpStatus;
|
||||||
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义异常返回
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
**/
|
||||||
|
public class CustomOauthExceptionSerializer extends StdSerializer<CustomOauthException>
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(CustomOauthExceptionSerializer.class);
|
||||||
|
|
||||||
|
public static final String BAD_CREDENTIALS = "Bad credentials";
|
||||||
|
|
||||||
|
public CustomOauthExceptionSerializer()
|
||||||
|
{
|
||||||
|
super(CustomOauthException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(CustomOauthException e, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
jsonGenerator.writeStartObject();
|
||||||
|
jsonGenerator.writeNumberField(AjaxResult.CODE_TAG, HttpStatus.ERROR);
|
||||||
|
if (StringUtils.equals(e.getMessage(), BAD_CREDENTIALS))
|
||||||
|
{
|
||||||
|
jsonGenerator.writeStringField(AjaxResult.MSG_TAG, "用户名或密码错误");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.warn("oauth2 认证异常 {} ", e);
|
||||||
|
jsonGenerator.writeStringField(AjaxResult.MSG_TAG, e.getMessage());
|
||||||
|
}
|
||||||
|
jsonGenerator.writeEndObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.ruoyi.auth.exception;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
|
||||||
|
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth2 自定义异常处理
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class CustomWebResponseExceptionTranslator implements WebResponseExceptionTranslator<OAuth2Exception>
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<OAuth2Exception> translate(Exception e)
|
||||||
|
{
|
||||||
|
return ResponseEntity.status(HttpStatus.OK).body(new CustomOauthException(e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.ruoyi.auth.handler;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.constant.Constants;
|
||||||
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
|
import com.ruoyi.system.api.RemoteLogService;
|
||||||
|
import com.ruoyi.system.api.model.LoginUser;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 认证成功处理
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class AuthenticationSuccessEventHandler implements ApplicationListener<AuthenticationSuccessEvent>
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private RemoteLogService remoteLogService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(AuthenticationSuccessEvent event)
|
||||||
|
{
|
||||||
|
Authentication authentication = (Authentication) event.getSource();
|
||||||
|
if (StringUtils.isNotEmpty(authentication.getAuthorities())
|
||||||
|
&& authentication.getPrincipal() instanceof LoginUser)
|
||||||
|
{
|
||||||
|
LoginUser user = (LoginUser) authentication.getPrincipal();
|
||||||
|
|
||||||
|
String username = user.getUsername();
|
||||||
|
|
||||||
|
// 记录用户登录日志
|
||||||
|
remoteLogService.saveLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.ruoyi.auth.service;
|
package com.ruoyi.auth.service;
|
||||||
|
|
||||||
|
import com.ruoyi.system.api.model.UserInfo;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import com.ruoyi.common.core.constant.Constants;
|
import com.ruoyi.common.core.constant.Constants;
|
||||||
|
|
@ -7,7 +8,7 @@ import com.ruoyi.common.core.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.common.core.domain.R;
|
||||||
import com.ruoyi.common.core.enums.UserStatus;
|
import com.ruoyi.common.core.enums.UserStatus;
|
||||||
import com.ruoyi.common.core.exception.BaseException;
|
import com.ruoyi.common.core.exception.BaseException;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.system.api.RemoteLogService;
|
import com.ruoyi.system.api.RemoteLogService;
|
||||||
import com.ruoyi.system.api.RemoteUserService;
|
import com.ruoyi.system.api.RemoteUserService;
|
||||||
|
|
@ -31,7 +32,7 @@ public class SysLoginService
|
||||||
/**
|
/**
|
||||||
* 登录
|
* 登录
|
||||||
*/
|
*/
|
||||||
public LoginUser login(String username, String password)
|
public UserInfo login(String username, String password)
|
||||||
{
|
{
|
||||||
// 用户名或密码为空 错误
|
// 用户名或密码为空 错误
|
||||||
if (StringUtils.isAnyBlank(username, password))
|
if (StringUtils.isAnyBlank(username, password))
|
||||||
|
|
@ -54,7 +55,7 @@ public class SysLoginService
|
||||||
throw new BaseException("用户名不在指定范围");
|
throw new BaseException("用户名不在指定范围");
|
||||||
}
|
}
|
||||||
// 查询用户信息
|
// 查询用户信息
|
||||||
R<LoginUser> userResult = remoteUserService.getUserInfo(username);
|
R<UserInfo> userResult = remoteUserService.getUserInfo(username);
|
||||||
|
|
||||||
if (R.FAIL == userResult.getCode())
|
if (R.FAIL == userResult.getCode())
|
||||||
{
|
{
|
||||||
|
|
@ -66,7 +67,7 @@ public class SysLoginService
|
||||||
remoteLogService.saveLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
|
remoteLogService.saveLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
|
||||||
throw new BaseException("登录用户:" + username + " 不存在");
|
throw new BaseException("登录用户:" + username + " 不存在");
|
||||||
}
|
}
|
||||||
LoginUser userInfo = userResult.getData();
|
UserInfo userInfo = userResult.getData();
|
||||||
SysUser user = userResult.getData().getSysUser();
|
SysUser user = userResult.getData().getSysUser();
|
||||||
if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
|
if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,12 @@ spring:
|
||||||
nacos:
|
nacos:
|
||||||
discovery:
|
discovery:
|
||||||
# 服务注册地址
|
# 服务注册地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
config:
|
config:
|
||||||
# 配置中心地址
|
# 配置中心地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
# 配置文件格式
|
# 配置文件格式
|
||||||
file-extension: yml
|
file-extension: yml
|
||||||
# 共享配置
|
# 共享配置
|
||||||
shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
shared-configs:
|
||||||
|
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,17 @@
|
||||||
<artifactId>swagger-annotations</artifactId>
|
<artifactId>swagger-annotations</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
||||||
|
|
@ -36,4 +36,14 @@ public class CacheConstants
|
||||||
* 授权信息字段
|
* 授权信息字段
|
||||||
*/
|
*/
|
||||||
public static final String AUTHORIZATION_HEADER = "authorization";
|
public static final String AUTHORIZATION_HEADER = "authorization";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oauth 缓存前缀
|
||||||
|
*/
|
||||||
|
public static final String OAUTH_ACCESS = "oauth:access:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oauth 客户端信息
|
||||||
|
*/
|
||||||
|
public static final String CLIENT_DETAILS_KEY = "oauth:client:details";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
package com.ruoyi.common.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限相关通用常量
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class SecurityConstants
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 令牌类型
|
||||||
|
*/
|
||||||
|
public static final String BEARER_TOKEN_TYPE = "Bearer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权token url
|
||||||
|
*/
|
||||||
|
public static final String AUTH_TOKEN = "/oauth/token";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注销token url
|
||||||
|
*/
|
||||||
|
public static final String TOKEN_LOGOUT = "/token/logout";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID字段
|
||||||
|
*/
|
||||||
|
public static final String DETAILS_USER_ID = "user_id";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名字段
|
||||||
|
*/
|
||||||
|
public static final String DETAILS_USERNAME = "username";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sys_oauth_client_details 表的字段,不包括client_id、client_secret
|
||||||
|
*/
|
||||||
|
public static final String CLIENT_FIELDS = "client_id, client_secret, resource_ids, scope, "
|
||||||
|
+ "authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, "
|
||||||
|
+ "refresh_token_validity, additional_information, autoapprove";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JdbcClientDetailsService 查询语句
|
||||||
|
*/
|
||||||
|
public static final String BASE_FIND_STATEMENT = "select " + CLIENT_FIELDS + " from sys_oauth_client_details";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按条件client_id 查询
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_SELECT_STATEMENT = BASE_FIND_STATEMENT + " where client_id = ?";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认的查询语句
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_FIND_STATEMENT = BASE_FIND_STATEMENT + " order by client_id";
|
||||||
|
}
|
||||||
|
|
@ -1,88 +1,91 @@
|
||||||
package com.ruoyi.common.core.utils;
|
//package com.ruoyi.common.core.utils;
|
||||||
|
//
|
||||||
import javax.servlet.http.HttpServletRequest;
|
//import javax.servlet.http.HttpServletRequest;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import com.ruoyi.common.core.constant.CacheConstants;
|
//import com.ruoyi.common.core.constant.CacheConstants;
|
||||||
import com.ruoyi.common.core.text.Convert;
|
//import com.ruoyi.common.core.text.Convert;
|
||||||
|
//
|
||||||
/**
|
///**
|
||||||
* 权限获取工具类
|
// * 权限获取工具类
|
||||||
*
|
// *
|
||||||
* @author ruoyi
|
// * @author ruoyi
|
||||||
*/
|
// */
|
||||||
public class SecurityUtils
|
//public class SecurityUtils
|
||||||
{
|
//{
|
||||||
/**
|
// /**
|
||||||
* 获取用户
|
// * 获取用户
|
||||||
*/
|
// */
|
||||||
public static String getUsername()
|
// public static String getUsername()
|
||||||
{
|
// {
|
||||||
String username = ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USERNAME);
|
// String username = ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USERNAME);
|
||||||
return ServletUtils.urlDecode(username);
|
// return ServletUtils.urlDecode(username);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 获取用户ID
|
// * 获取用户ID
|
||||||
*/
|
// */
|
||||||
public static Long getUserId()
|
// public static Long getUserId()
|
||||||
{
|
// {
|
||||||
return Convert.toLong(ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USER_ID));
|
// return Convert.toLong(ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USER_ID));
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 获取请求token
|
// * 获取请求token
|
||||||
*/
|
// */
|
||||||
public static String getToken()
|
// public static String getToken()
|
||||||
{
|
// {
|
||||||
return getToken(ServletUtils.getRequest());
|
// return getToken(ServletUtils.getRequest());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 根据request获取请求token
|
// * 根据request获取请求token
|
||||||
*/
|
// */
|
||||||
public static String getToken(HttpServletRequest request)
|
// public static String getToken(HttpServletRequest request)
|
||||||
{
|
// {
|
||||||
String token = ServletUtils.getRequest().getHeader(CacheConstants.HEADER);
|
// String token = ServletUtils.getRequest().getHeader(CacheConstants.HEADER);
|
||||||
if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX))
|
// if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX))
|
||||||
{
|
// {
|
||||||
token = token.replace(CacheConstants.TOKEN_PREFIX, "");
|
// token = token.replace(CacheConstants.TOKEN_PREFIX, "");
|
||||||
}
|
// }
|
||||||
return token;
|
// return token;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 是否为管理员
|
// * 是否为管理员
|
||||||
*
|
// *
|
||||||
* @param userId 用户ID
|
// * @param userId 用户ID
|
||||||
* @return 结果
|
// * @return 结果
|
||||||
*/
|
// */
|
||||||
public static boolean isAdmin(Long userId)
|
// public static boolean isAdmin(Long userId)
|
||||||
{
|
// {
|
||||||
return userId != null && 1L == userId;
|
// return userId != null && 1L == userId;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 生成BCryptPasswordEncoder密码
|
// * 生成BCryptPasswordEncoder密码
|
||||||
*
|
// *
|
||||||
* @param password 密码
|
// * @param password 密码
|
||||||
* @return 加密字符串
|
// * @return 加密字符串
|
||||||
*/
|
// */
|
||||||
public static String encryptPassword(String password)
|
// public static String encryptPassword(String password)
|
||||||
{
|
// {
|
||||||
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
// BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||||
return passwordEncoder.encode(password);
|
// return passwordEncoder.encode(password);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 判断密码是否相同
|
// * 判断密码是否相同
|
||||||
*
|
// *
|
||||||
* @param rawPassword 真实密码
|
// * @param rawPassword 真实密码
|
||||||
* @param encodedPassword 加密后字符
|
// * @param encodedPassword 加密后字符
|
||||||
* @return 结果
|
// * @return 结果
|
||||||
*/
|
// */
|
||||||
public static boolean matchesPassword(String rawPassword, String encodedPassword)
|
// public static boolean matchesPassword(String rawPassword, String encodedPassword)
|
||||||
{
|
// {
|
||||||
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
// BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||||
return passwordEncoder.matches(rawPassword, encodedPassword);
|
// return passwordEncoder.matches(rawPassword, encodedPassword);
|
||||||
}
|
// }
|
||||||
}
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.aspectj.lang.Signature;
|
import org.aspectj.lang.Signature;
|
||||||
import org.aspectj.lang.annotation.AfterReturning;
|
import org.aspectj.lang.annotation.AfterReturning;
|
||||||
|
|
@ -20,7 +22,6 @@ import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
|
||||||
import com.ruoyi.common.core.utils.ServletUtils;
|
import com.ruoyi.common.core.utils.ServletUtils;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.common.core.utils.ip.IpUtils;
|
import com.ruoyi.common.core.utils.ip.IpUtils;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,12 @@
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- Spring Security Oauth2 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-oauth2</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- RuoYi Api System -->
|
<!-- RuoYi Api System -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,14 @@ import java.lang.annotation.Inherited;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import com.ruoyi.common.security.config.SecurityImportBeanDefinitionRegistrar;
|
||||||
|
import com.ruoyi.common.security.feign.FeignConfig;
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
import com.ruoyi.common.security.config.ApplicationConfig;
|
import com.ruoyi.common.security.config.ApplicationConfig;
|
||||||
import com.ruoyi.common.security.feign.FeignAutoConfiguration;
|
|
||||||
|
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
|
@ -24,8 +26,7 @@ import com.ruoyi.common.security.feign.FeignAutoConfiguration;
|
||||||
// 开启线程异步执行
|
// 开启线程异步执行
|
||||||
@EnableAsync
|
@EnableAsync
|
||||||
// 自动加载类
|
// 自动加载类
|
||||||
@Import({ ApplicationConfig.class, FeignAutoConfiguration.class })
|
@Import({ ApplicationConfig.class, FeignConfig.class , SecurityImportBeanDefinitionRegistrar.class})
|
||||||
public @interface EnableCustomConfig
|
public @interface EnableCustomConfig {
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import org.aspectj.lang.annotation.Around;
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.reflect.MethodSignature;
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.PatternMatchUtils;
|
import org.springframework.util.PatternMatchUtils;
|
||||||
|
|
@ -111,11 +112,11 @@ public class PreAuthorizeAspect
|
||||||
public boolean hasPermi(String permission)
|
public boolean hasPermi(String permission)
|
||||||
{
|
{
|
||||||
LoginUser userInfo = tokenService.getLoginUser();
|
LoginUser userInfo = tokenService.getLoginUser();
|
||||||
if (StringUtils.isEmpty(userInfo) || CollectionUtils.isEmpty(userInfo.getPermissions()))
|
if (StringUtils.isEmpty(userInfo) || CollectionUtils.isEmpty(userInfo.getAuthorities()))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return hasPermissions(userInfo.getPermissions(), permission);
|
return hasPermissions(userInfo.getAuthorities(), permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -142,7 +143,7 @@ public class PreAuthorizeAspect
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Collection<String> authorities = userInfo.getPermissions();
|
Collection<GrantedAuthority> authorities = userInfo.getAuthorities();
|
||||||
for (String permission : permissions)
|
for (String permission : permissions)
|
||||||
{
|
{
|
||||||
if (permission != null && hasPermissions(authorities, permission))
|
if (permission != null && hasPermissions(authorities, permission))
|
||||||
|
|
@ -217,9 +218,8 @@ public class PreAuthorizeAspect
|
||||||
* @param permission 权限字符串
|
* @param permission 权限字符串
|
||||||
* @return 用户是否具备某权限
|
* @return 用户是否具备某权限
|
||||||
*/
|
*/
|
||||||
private boolean hasPermissions(Collection<String> authorities, String permission)
|
private boolean hasPermissions(Collection<GrantedAuthority> authorities, String permission)
|
||||||
{
|
{
|
||||||
return authorities.stream().filter(StringUtils::hasText)
|
return authorities.stream().filter(grantedAuthority-> {return StringUtils.hasText(grantedAuthority.getAuthority());}).anyMatch(grantedAuthority -> ALL_PERMISSION.contains(grantedAuthority.getAuthority()) || PatternMatchUtils.simpleMatch(permission, grantedAuthority.getAuthority()));
|
||||||
.anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(permission, x));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.ruoyi.common.security.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Configurable;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 忽略服务间的认证
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
**/
|
||||||
|
@Component
|
||||||
|
@Configurable
|
||||||
|
@ConfigurationProperties(prefix = "security.oauth2.ignore")
|
||||||
|
public class AuthIgnoreConfig
|
||||||
|
{
|
||||||
|
private List<String> urls = new ArrayList<>();
|
||||||
|
|
||||||
|
public List<String> getUrls()
|
||||||
|
{
|
||||||
|
return urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrls(List<String> urls)
|
||||||
|
{
|
||||||
|
this.urls = urls;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.ruoyi.common.security.config;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.constant.SecurityConstants;
|
||||||
|
import com.ruoyi.common.core.text.Convert;
|
||||||
|
import com.ruoyi.system.api.model.LoginUser;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
|
import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://my.oschina.net/giegie/blog/3023768 根据checktoken 的结果转化用户信息
|
||||||
|
*
|
||||||
|
* @author lengleng
|
||||||
|
*/
|
||||||
|
public class CommonUserConverter implements UserAuthenticationConverter
|
||||||
|
{
|
||||||
|
private static final String N_A = "N/A";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将授权信息返回到资源服务
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, ?> convertUserAuthentication(Authentication userAuthentication)
|
||||||
|
{
|
||||||
|
Map<String, Object> authMap = new LinkedHashMap<>();
|
||||||
|
authMap.put(USERNAME, userAuthentication.getName());
|
||||||
|
if (userAuthentication.getAuthorities() != null && !userAuthentication.getAuthorities().isEmpty())
|
||||||
|
{
|
||||||
|
authMap.put(AUTHORITIES, AuthorityUtils.authorityListToSet(userAuthentication.getAuthorities()));
|
||||||
|
}
|
||||||
|
return authMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户认证信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Authentication extractAuthentication(Map<String, ?> map)
|
||||||
|
{
|
||||||
|
if (map.containsKey(USERNAME))
|
||||||
|
{
|
||||||
|
Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
|
||||||
|
Long userId = Convert.toLong(map.get(SecurityConstants.DETAILS_USER_ID));
|
||||||
|
String username = (String) map.get(SecurityConstants.DETAILS_USERNAME);
|
||||||
|
LoginUser user = new LoginUser(userId,username, true, true, true, true, authorities);
|
||||||
|
return new UsernamePasswordAuthenticationToken(user, N_A, authorities);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取权限资源信息
|
||||||
|
*/
|
||||||
|
private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map)
|
||||||
|
{
|
||||||
|
Object authorities = map.get(AUTHORITIES);
|
||||||
|
if (authorities instanceof String)
|
||||||
|
{
|
||||||
|
return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);
|
||||||
|
}
|
||||||
|
if (authorities instanceof Collection)
|
||||||
|
{
|
||||||
|
return AuthorityUtils.commaSeparatedStringToAuthorityList(
|
||||||
|
StringUtils.collectionToCommaDelimitedString((Collection<?>) authorities));
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Authorities must be either a String or a Collection");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.ruoyi.common.security.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @EnableGlobalMethodSecurity(securedEnabled=true)
|
||||||
|
* 开启@Secured 注解过滤权限
|
||||||
|
*
|
||||||
|
* @EnableGlobalMethodSecurity(jsr250Enabled=true)
|
||||||
|
* 开启@RolesAllowed 注解过滤权限
|
||||||
|
*
|
||||||
|
* @EnableGlobalMethodSecurity(prePostEnabled=true)
|
||||||
|
* 使用表达式时间方法级别的安全性 4个注解可用
|
||||||
|
* -@PreAuthorize 在方法调用之前,基于表达式的计算结果来限制对方法的访问
|
||||||
|
* -@PostAuthorize 允许方法调用,但是如果表达式计算结果为false,将抛出一个安全性异常
|
||||||
|
* -@PostFilter 允许方法调用,但必须按照表达式来过滤方法的结果
|
||||||
|
* -@PreFilter 允许方法调用,但必须在进入方法之前过滤输入值
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||||
|
public class MethodSecurityConfig {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.ruoyi.common.security.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.security.oauth2.OAuth2ClientProperties;
|
||||||
|
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
|
||||||
|
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||||
|
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
|
||||||
|
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
|
||||||
|
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
|
||||||
|
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
|
||||||
|
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
|
||||||
|
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
|
||||||
|
import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
|
||||||
|
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oauth2 服务配置
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableResourceServer
|
||||||
|
public class ResourceServerConfig extends ResourceServerConfigurerAdapter
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private ResourceServerProperties resourceServerProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OAuth2ClientProperties oAuth2ClientProperties;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AuthIgnoreConfig authIgnoreConfig()
|
||||||
|
{
|
||||||
|
return new AuthIgnoreConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@LoadBalanced
|
||||||
|
public RestTemplate restTemplate()
|
||||||
|
{
|
||||||
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
|
restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
|
||||||
|
return restTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ResourceServerTokenServices tokenServices()
|
||||||
|
{
|
||||||
|
RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
|
||||||
|
DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
|
||||||
|
UserAuthenticationConverter userTokenConverter = new CommonUserConverter();
|
||||||
|
accessTokenConverter.setUserTokenConverter(userTokenConverter);
|
||||||
|
remoteTokenServices.setCheckTokenEndpointUrl(resourceServerProperties.getTokenInfoUri());
|
||||||
|
remoteTokenServices.setClientId(oAuth2ClientProperties.getClientId());
|
||||||
|
remoteTokenServices.setClientSecret(oAuth2ClientProperties.getClientSecret());
|
||||||
|
remoteTokenServices.setRestTemplate(restTemplate());
|
||||||
|
remoteTokenServices.setAccessTokenConverter(accessTokenConverter);
|
||||||
|
return remoteTokenServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(HttpSecurity http) throws Exception
|
||||||
|
{
|
||||||
|
http.csrf().disable();
|
||||||
|
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
|
||||||
|
.authorizeRequests();
|
||||||
|
// 不登录可以访问
|
||||||
|
authIgnoreConfig().getUrls().forEach(url -> registry.antMatchers(url).permitAll());
|
||||||
|
registry.anyRequest().authenticated();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(ResourceServerSecurityConfigurer resources)
|
||||||
|
{
|
||||||
|
resources.tokenServices(tokenServices());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.ruoyi.common.security.config;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
|
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||||
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入 SecurityImportBeanDefinitionRegistrar 自动加载类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class SecurityImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry)
|
||||||
|
{
|
||||||
|
Class<ResourceServerConfig> aClass = ResourceServerConfig.class;
|
||||||
|
String beanName = StringUtils.uncapitalize(aClass.getSimpleName());
|
||||||
|
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(ResourceServerConfig.class);
|
||||||
|
registry.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
package com.ruoyi.common.security.feign;
|
//package com.ruoyi.common.security.feign;
|
||||||
|
//
|
||||||
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 feign.RequestInterceptor;
|
//import feign.RequestInterceptor;
|
||||||
|
//
|
||||||
/**
|
///**
|
||||||
* Feign 配置注册
|
// * Feign 配置注册
|
||||||
*
|
// *
|
||||||
* @author ruoyi
|
// * @author ruoyi
|
||||||
**/
|
// **/
|
||||||
@Configuration
|
//@Configuration
|
||||||
public class FeignAutoConfiguration
|
//public class FeignAutoConfiguration
|
||||||
{
|
//{
|
||||||
@Bean
|
// @Bean
|
||||||
public RequestInterceptor requestInterceptor()
|
// public RequestInterceptor requestInterceptor()
|
||||||
{
|
// {
|
||||||
return new FeignRequestInterceptor();
|
// return new FeignRequestInterceptor();
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.ruoyi.common.security.feign;
|
||||||
|
|
||||||
|
import feign.RequestInterceptor;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feign配置注册
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
**/
|
||||||
|
@Configuration
|
||||||
|
public class FeignConfig
|
||||||
|
{
|
||||||
|
@Bean
|
||||||
|
public RequestInterceptor requestInterceptor()
|
||||||
|
{
|
||||||
|
return new OAuth2FeignRequestInterceptor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,45 +1,45 @@
|
||||||
package com.ruoyi.common.security.feign;
|
//package com.ruoyi.common.security.feign;
|
||||||
|
//
|
||||||
import java.util.Map;
|
//import java.util.Map;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
//import javax.servlet.http.HttpServletRequest;
|
||||||
import org.springframework.stereotype.Component;
|
//import org.springframework.stereotype.Component;
|
||||||
import com.ruoyi.common.core.constant.CacheConstants;
|
//import com.ruoyi.common.core.constant.CacheConstants;
|
||||||
import com.ruoyi.common.core.utils.ServletUtils;
|
//import com.ruoyi.common.core.utils.ServletUtils;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
//import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import feign.RequestInterceptor;
|
//import feign.RequestInterceptor;
|
||||||
import feign.RequestTemplate;
|
//import feign.RequestTemplate;
|
||||||
|
//
|
||||||
/**
|
///**
|
||||||
* feign 请求拦截器
|
// * feign 请求拦截器
|
||||||
*
|
// *
|
||||||
* @author ruoyi
|
// * @author ruoyi
|
||||||
*/
|
// */
|
||||||
@Component
|
//@Component
|
||||||
public class FeignRequestInterceptor implements RequestInterceptor
|
//public class FeignRequestInterceptor implements RequestInterceptor
|
||||||
{
|
//{
|
||||||
@Override
|
// @Override
|
||||||
public void apply(RequestTemplate requestTemplate)
|
// public void apply(RequestTemplate requestTemplate)
|
||||||
{
|
// {
|
||||||
HttpServletRequest httpServletRequest = ServletUtils.getRequest();
|
// HttpServletRequest httpServletRequest = ServletUtils.getRequest();
|
||||||
if (StringUtils.isNotNull(httpServletRequest))
|
// if (StringUtils.isNotNull(httpServletRequest))
|
||||||
{
|
// {
|
||||||
Map<String, String> headers = ServletUtils.getHeaders(httpServletRequest);
|
// Map<String, String> headers = ServletUtils.getHeaders(httpServletRequest);
|
||||||
// 传递用户信息请求头,防止丢失
|
// // 传递用户信息请求头,防止丢失
|
||||||
String userId = headers.get(CacheConstants.DETAILS_USER_ID);
|
// String userId = headers.get(CacheConstants.DETAILS_USER_ID);
|
||||||
if (StringUtils.isNotEmpty(userId))
|
// if (StringUtils.isNotEmpty(userId))
|
||||||
{
|
// {
|
||||||
requestTemplate.header(CacheConstants.DETAILS_USER_ID, userId);
|
// requestTemplate.header(CacheConstants.DETAILS_USER_ID, userId);
|
||||||
}
|
// }
|
||||||
String userName = headers.get(CacheConstants.DETAILS_USERNAME);
|
// String userName = headers.get(CacheConstants.DETAILS_USERNAME);
|
||||||
if (StringUtils.isNotEmpty(userName))
|
// if (StringUtils.isNotEmpty(userName))
|
||||||
{
|
// {
|
||||||
requestTemplate.header(CacheConstants.DETAILS_USERNAME, userName);
|
// requestTemplate.header(CacheConstants.DETAILS_USERNAME, userName);
|
||||||
}
|
// }
|
||||||
String authentication = headers.get(CacheConstants.AUTHORIZATION_HEADER);
|
// String authentication = headers.get(CacheConstants.AUTHORIZATION_HEADER);
|
||||||
if (StringUtils.isNotEmpty(authentication))
|
// if (StringUtils.isNotEmpty(authentication))
|
||||||
{
|
// {
|
||||||
requestTemplate.header(CacheConstants.AUTHORIZATION_HEADER, authentication);
|
// requestTemplate.header(CacheConstants.AUTHORIZATION_HEADER, authentication);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.ruoyi.common.security.feign;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.constant.SecurityConstants;
|
||||||
|
import feign.RequestInterceptor;
|
||||||
|
import feign.RequestTemplate;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* feign 请求拦截器
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class OAuth2FeignRequestInterceptor implements RequestInterceptor
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void apply(RequestTemplate requestTemplate)
|
||||||
|
{
|
||||||
|
SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||||
|
Authentication authentication = securityContext.getAuthentication();
|
||||||
|
if (authentication != null && authentication.getDetails() instanceof OAuth2AuthenticationDetails)
|
||||||
|
{
|
||||||
|
OAuth2AuthenticationDetails dateils = (OAuth2AuthenticationDetails) authentication.getDetails();
|
||||||
|
requestTemplate.header(HttpHeaders.AUTHORIZATION,
|
||||||
|
String.format("%s %s", SecurityConstants.BEARER_TOKEN_TYPE, dateils.getTokenValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.ruoyi.common.security.handler;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.ruoyi.common.core.constant.HttpStatus;
|
||||||
|
import com.ruoyi.common.core.domain.R;
|
||||||
|
import com.ruoyi.common.core.utils.ServletUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义访问无权限资源时的异常
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class CustomAccessDeniedHandler extends OAuth2AccessDeniedHandler
|
||||||
|
{
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(CustomAccessDeniedHandler.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException authException)
|
||||||
|
{
|
||||||
|
logger.info("权限不足,请联系管理员 {}", request.getRequestURI());
|
||||||
|
|
||||||
|
String msg = authException.getMessage();
|
||||||
|
ServletUtils.renderString(response, JSON.toJSONString(R.fail(HttpStatus.FORBIDDEN, msg)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.ruoyi.common.security.handler;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.R;
|
||||||
|
import com.ruoyi.system.api.RemoteUserService;
|
||||||
|
import com.ruoyi.system.api.model.LoginUser;
|
||||||
|
import com.ruoyi.system.api.model.UserInfo;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author alikes
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RemoteUserService remoteUserService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
|
||||||
|
if(authentication instanceof LoginUser){
|
||||||
|
LoginUser loginUser = (LoginUser) authentication;
|
||||||
|
R<UserInfo> res = remoteUserService.getUserInfo(loginUser.getSysUser().getUserName());
|
||||||
|
loginUser.setRoles(res.getData().getRoles());
|
||||||
|
loginUser.setPermissions(res.getData().getPermissions());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,168 @@
|
||||||
|
package com.ruoyi.common.security.service;
|
||||||
|
|
||||||
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.system.api.model.LoginUser;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.PatternMatchUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义权限实现
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Service("ss")
|
||||||
|
public class PermissionService
|
||||||
|
{
|
||||||
|
/** 所有权限标识 */
|
||||||
|
private static final String ALL_PERMISSION = "*:*:*";
|
||||||
|
|
||||||
|
/** 管理员角色权限标识 */
|
||||||
|
private static final String SUPER_ADMIN = "admin";
|
||||||
|
|
||||||
|
private static final String ROLE_DELIMETER = ",";
|
||||||
|
|
||||||
|
private static final String PERMISSION_DELIMETER = ",";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否具备某权限
|
||||||
|
*
|
||||||
|
* @param permission 权限字符串
|
||||||
|
* @return 用户是否具备某权限
|
||||||
|
*/
|
||||||
|
public boolean hasPermi(String permission)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(permission))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (StringUtils.isEmpty(loginUser) || CollectionUtils.isEmpty(loginUser.getAuthorities()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return hasPermissions(loginUser.getAuthorities(), permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否不具备某权限,与 hasPermi逻辑相反
|
||||||
|
*
|
||||||
|
* @param permission 权限字符串
|
||||||
|
* @return 用户是否不具备某权限
|
||||||
|
*/
|
||||||
|
public boolean lacksPermi(String permission)
|
||||||
|
{
|
||||||
|
return hasPermi(permission) != true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否具有以下任意一个权限
|
||||||
|
*
|
||||||
|
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
|
||||||
|
* @return 用户是否具有以下任意一个权限
|
||||||
|
*/
|
||||||
|
public boolean hasAnyPermi(String permissions)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(permissions))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (StringUtils.isEmpty(loginUser) || CollectionUtils.isEmpty(loginUser.getAuthorities()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Collection<? extends GrantedAuthority> authorities = loginUser.getAuthorities();
|
||||||
|
for (String permission : permissions.split(PERMISSION_DELIMETER))
|
||||||
|
{
|
||||||
|
if (permission != null && hasPermissions(authorities, permission))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断用户是否拥有某个角色
|
||||||
|
*
|
||||||
|
* @param role 角色字符串
|
||||||
|
* @return 用户是否具备某角色
|
||||||
|
*/
|
||||||
|
public boolean hasRole(String role)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(role))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (StringUtils.isEmpty(loginUser) || CollectionUtils.isEmpty(loginUser.getAuthorities()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (GrantedAuthority authorities : loginUser.getAuthorities())
|
||||||
|
{
|
||||||
|
String roleKey = authorities.getAuthority();
|
||||||
|
if (SUPER_ADMIN.contains(roleKey) || roleKey.contains(role))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否不具备某角色,与 isRole逻辑相反。
|
||||||
|
*
|
||||||
|
* @param role 角色名称
|
||||||
|
* @return 用户是否不具备某角色
|
||||||
|
*/
|
||||||
|
public boolean lacksRole(String role)
|
||||||
|
{
|
||||||
|
return hasRole(role) != true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否具有以下任意一个角色
|
||||||
|
*
|
||||||
|
* @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
|
||||||
|
* @return 用户是否具有以下任意一个角色
|
||||||
|
*/
|
||||||
|
public boolean hasAnyRoles(String roles)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(roles))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
if (StringUtils.isEmpty(loginUser) || CollectionUtils.isEmpty(loginUser.getAuthorities()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (String role : roles.split(ROLE_DELIMETER))
|
||||||
|
{
|
||||||
|
if (hasRole(role))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否包含权限
|
||||||
|
*
|
||||||
|
* @param authorities 权限列表
|
||||||
|
* @param permission 权限字符串
|
||||||
|
* @return 用户是否具备某权限
|
||||||
|
*/
|
||||||
|
private boolean hasPermissions(Collection<? extends GrantedAuthority> authorities, String permission)
|
||||||
|
{
|
||||||
|
return authorities.stream().map(GrantedAuthority::getAuthority).filter(StringUtils::hasText)
|
||||||
|
.anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(permission, x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.ruoyi.common.security.service;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.constant.CacheConstants;
|
||||||
|
import com.ruoyi.common.core.constant.SecurityConstants;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||||
|
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重写原生方法支持redis缓存
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class RedisClientDetailsService extends JdbcClientDetailsService
|
||||||
|
{
|
||||||
|
public RedisClientDetailsService(DataSource dataSource)
|
||||||
|
{
|
||||||
|
super(dataSource);
|
||||||
|
super.setSelectClientDetailsSql(SecurityConstants.DEFAULT_SELECT_STATEMENT);
|
||||||
|
super.setFindClientDetailsSql(SecurityConstants.DEFAULT_FIND_STATEMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Cacheable(value = CacheConstants.CLIENT_DETAILS_KEY, key = "#clientId", unless = "#result == null")
|
||||||
|
public ClientDetails loadClientByClientId(String clientId)
|
||||||
|
{
|
||||||
|
return super.loadClientByClientId(clientId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,12 +4,13 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import com.ruoyi.common.core.constant.CacheConstants;
|
import com.ruoyi.common.core.constant.CacheConstants;
|
||||||
import com.ruoyi.common.core.constant.Constants;
|
import com.ruoyi.common.core.constant.Constants;
|
||||||
import com.ruoyi.common.core.utils.IdUtils;
|
import com.ruoyi.common.core.utils.IdUtils;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
|
||||||
import com.ruoyi.common.core.utils.ServletUtils;
|
import com.ruoyi.common.core.utils.ServletUtils;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.common.core.utils.ip.IpUtils;
|
import com.ruoyi.common.core.utils.ip.IpUtils;
|
||||||
|
|
@ -41,7 +42,7 @@ public class TokenService
|
||||||
// 生成token
|
// 生成token
|
||||||
String token = IdUtils.fastUUID();
|
String token = IdUtils.fastUUID();
|
||||||
loginUser.setToken(token);
|
loginUser.setToken(token);
|
||||||
loginUser.setUserid(loginUser.getSysUser().getUserId());
|
loginUser.setUserId(loginUser.getSysUser().getUserId());
|
||||||
loginUser.setUsername(loginUser.getSysUser().getUserName());
|
loginUser.setUsername(loginUser.getSysUser().getUserName());
|
||||||
loginUser.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
|
loginUser.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
|
||||||
refreshToken(loginUser);
|
refreshToken(loginUser);
|
||||||
|
|
@ -71,15 +72,17 @@ public class TokenService
|
||||||
*/
|
*/
|
||||||
public LoginUser getLoginUser(HttpServletRequest request)
|
public LoginUser getLoginUser(HttpServletRequest request)
|
||||||
{
|
{
|
||||||
// 获取请求携带的令牌
|
// // 获取请求携带的令牌
|
||||||
String token = SecurityUtils.getToken(request);
|
// String token = SecurityUtils.getToken(request);
|
||||||
if (StringUtils.isNotEmpty(token))
|
// if (StringUtils.isNotEmpty(token))
|
||||||
{
|
// {
|
||||||
String userKey = getTokenKey(token);
|
// String userKey = getTokenKey(token);
|
||||||
LoginUser user = redisService.getCacheObject(userKey);
|
// LoginUser user = redisService.getCacheObject(userKey);
|
||||||
return user;
|
// LoginUser user = SecurityUtils.getLoginUser();
|
||||||
}
|
//
|
||||||
return null;
|
// }
|
||||||
|
// return null;
|
||||||
|
return SecurityUtils.getLoginUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
package com.ruoyi.common.security.service;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.R;
|
||||||
|
import com.ruoyi.common.core.enums.UserStatus;
|
||||||
|
import com.ruoyi.common.core.exception.BaseException;
|
||||||
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
|
import com.ruoyi.system.api.RemoteUserService;
|
||||||
|
import com.ruoyi.system.api.domain.SysUser;
|
||||||
|
import com.ruoyi.system.api.model.LoginUser;
|
||||||
|
import com.ruoyi.system.api.model.UserInfo;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户信息处理
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Service("defaultUserDetailsService")
|
||||||
|
public class UserDetailsServiceImpl implements UserDetailsService
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RemoteUserService remoteUserService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoginUser loadUserByUsername(String username)
|
||||||
|
{
|
||||||
|
R<UserInfo> userResult = remoteUserService.getUserInfo(username);
|
||||||
|
checkUser(userResult, username);
|
||||||
|
return getUserDetails(userResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkUser(R<UserInfo> userResult, String username)
|
||||||
|
{
|
||||||
|
if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData()))
|
||||||
|
{
|
||||||
|
log.info("登录用户:{} 不存在.", username);
|
||||||
|
throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
|
||||||
|
}
|
||||||
|
else if (UserStatus.DELETED.getCode().equals(userResult.getData().getSysUser().getDelFlag()))
|
||||||
|
{
|
||||||
|
log.info("登录用户:{} 已被删除.", username);
|
||||||
|
throw new BaseException("对不起,您的账号:" + username + " 已被删除");
|
||||||
|
}
|
||||||
|
else if (UserStatus.DISABLE.getCode().equals(userResult.getData().getSysUser().getStatus()))
|
||||||
|
{
|
||||||
|
log.info("登录用户:{} 已被停用.", username);
|
||||||
|
throw new BaseException("对不起,您的账号:" + username + " 已停用");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LoginUser getUserDetails(R<UserInfo> result)
|
||||||
|
{
|
||||||
|
UserInfo info = result.getData();
|
||||||
|
Set<String> dbAuthsSet = new HashSet<String>();
|
||||||
|
if (StringUtils.isNotEmpty(info.getRoles()))
|
||||||
|
{
|
||||||
|
// 获取角色
|
||||||
|
dbAuthsSet.addAll(info.getRoles());
|
||||||
|
// 获取权限
|
||||||
|
dbAuthsSet.addAll(info.getPermissions());
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<? extends GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(dbAuthsSet.toArray(new String[0]));
|
||||||
|
SysUser user = info.getSysUser();
|
||||||
|
LoginUser loginUser = new LoginUser(user.getUserId(), user.getUserName(), user.getPassword(), true, true, true, true, authorities);
|
||||||
|
loginUser.setPermissions(info.getPermissions());
|
||||||
|
loginUser.setRoles(info.getRoles());
|
||||||
|
return loginUser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
package com.ruoyi.common.security.utils;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.text.Convert;
|
||||||
|
import com.ruoyi.system.api.model.LoginUser;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限获取工具类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class SecurityUtils
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取Authentication
|
||||||
|
*/
|
||||||
|
public static Authentication getAuthentication()
|
||||||
|
{
|
||||||
|
return SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户
|
||||||
|
*/
|
||||||
|
public static String getUsername()
|
||||||
|
{
|
||||||
|
return getLoginUser().getUsername();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户
|
||||||
|
*/
|
||||||
|
public static LoginUser getLoginUser(Authentication authentication)
|
||||||
|
{
|
||||||
|
Object principal = authentication.getPrincipal();
|
||||||
|
if (principal instanceof LoginUser)
|
||||||
|
{
|
||||||
|
return (LoginUser) principal;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户ID
|
||||||
|
*/
|
||||||
|
public static Long getUserId(){
|
||||||
|
return Convert.toLong(getLoginUser().getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户
|
||||||
|
*/
|
||||||
|
public static LoginUser getLoginUser()
|
||||||
|
{
|
||||||
|
Authentication authentication = getAuthentication();
|
||||||
|
if (authentication == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return getLoginUser(authentication);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成BCryptPasswordEncoder密码
|
||||||
|
*
|
||||||
|
* @param password 密码
|
||||||
|
* @return 加密字符串
|
||||||
|
*/
|
||||||
|
public static String encryptPassword(String password)
|
||||||
|
{
|
||||||
|
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||||
|
return passwordEncoder.encode(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断密码是否相同
|
||||||
|
*
|
||||||
|
* @param rawPassword 真实密码
|
||||||
|
* @param encodedPassword 加密后字符
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public static boolean matchesPassword(String rawPassword, String encodedPassword)
|
||||||
|
{
|
||||||
|
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||||
|
return passwordEncoder.matches(rawPassword, encodedPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为管理员
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public static boolean isAdmin(Long userId)
|
||||||
|
{
|
||||||
|
return userId != null && 1L == userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,11 +13,7 @@ import com.google.common.base.Predicates;
|
||||||
import springfox.documentation.builders.ApiInfoBuilder;
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
import springfox.documentation.builders.PathSelectors;
|
import springfox.documentation.builders.PathSelectors;
|
||||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
import springfox.documentation.service.ApiInfo;
|
import springfox.documentation.service.*;
|
||||||
import springfox.documentation.service.ApiKey;
|
|
||||||
import springfox.documentation.service.AuthorizationScope;
|
|
||||||
import springfox.documentation.service.Contact;
|
|
||||||
import springfox.documentation.service.SecurityReference;
|
|
||||||
import springfox.documentation.spi.DocumentationType;
|
import springfox.documentation.spi.DocumentationType;
|
||||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||||
import springfox.documentation.spring.web.plugins.Docket;
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
|
@ -96,9 +92,20 @@ public class SwaggerAutoConfiguration
|
||||||
.securityReferences(defaultAuth())
|
.securityReferences(defaultAuth())
|
||||||
.forPaths(PathSelectors.regex("^(?!auth).*$"))
|
.forPaths(PathSelectors.regex("^(?!auth).*$"))
|
||||||
.build());
|
.build());
|
||||||
|
securityContexts.add(SecurityContext.builder()
|
||||||
|
.securityReferences(defaultAuth())
|
||||||
|
.forPaths(PathSelectors.regex(swaggerProperties().getAuthorization().getAuthRegex()))
|
||||||
|
.build());
|
||||||
return securityContexts;
|
return securityContexts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// private SecurityContext securityContext(){
|
||||||
|
// return SecurityContext.builder()
|
||||||
|
// .securityReferences(defaultAuth())
|
||||||
|
// .forPaths(PathSelectors.regex(swaggerProperties().getAuthorization().getAuthRegex()))
|
||||||
|
// .build();
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认的全局鉴权策略
|
* 默认的全局鉴权策略
|
||||||
*
|
*
|
||||||
|
|
@ -114,6 +121,15 @@ public class SwaggerAutoConfiguration
|
||||||
return securityReferences;
|
return securityReferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private OAuth securitySchema()
|
||||||
|
{
|
||||||
|
ArrayList<AuthorizationScope> authorizationScopeList = new ArrayList<>();
|
||||||
|
swaggerProperties().getAuthorization().getAuthorizationScopeList().forEach(authorizationScope -> authorizationScopeList.add(new AuthorizationScope(authorizationScope.getScope(), authorizationScope.getDescription())));
|
||||||
|
ArrayList<GrantType> grantTypes = new ArrayList<>();
|
||||||
|
swaggerProperties().getAuthorization().getTokenUrlList().forEach(tokenUrl -> grantTypes.add(new ResourceOwnerPasswordCredentialsGrant(tokenUrl)));
|
||||||
|
return new OAuth(swaggerProperties().getAuthorization().getName(), authorizationScopeList, grantTypes);
|
||||||
|
}
|
||||||
|
|
||||||
private ApiInfo apiInfo(SwaggerProperties swaggerProperties)
|
private ApiInfo apiInfo(SwaggerProperties swaggerProperties)
|
||||||
{
|
{
|
||||||
return new ApiInfoBuilder()
|
return new ApiInfoBuilder()
|
||||||
|
|
|
||||||
|
|
@ -1,125 +1,125 @@
|
||||||
package com.ruoyi.gateway.filter;
|
//package com.ruoyi.gateway.filter;
|
||||||
|
//
|
||||||
import javax.annotation.Resource;
|
//import javax.annotation.Resource;
|
||||||
import org.slf4j.Logger;
|
//import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
//import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
//import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
//import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||||
import org.springframework.core.Ordered;
|
//import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
//import org.springframework.core.io.buffer.DataBufferFactory;
|
||||||
import org.springframework.data.redis.core.ValueOperations;
|
//import org.springframework.data.redis.core.ValueOperations;
|
||||||
import org.springframework.http.HttpStatus;
|
//import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
//import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
//import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
//import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||||
import org.springframework.stereotype.Component;
|
//import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
//import org.springframework.web.server.ServerWebExchange;
|
||||||
import com.alibaba.fastjson.JSON;
|
//import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
//import com.alibaba.fastjson.JSONObject;
|
||||||
import com.ruoyi.common.core.constant.CacheConstants;
|
//import com.ruoyi.common.core.constant.CacheConstants;
|
||||||
import com.ruoyi.common.core.constant.Constants;
|
//import com.ruoyi.common.core.constant.Constants;
|
||||||
import com.ruoyi.common.core.domain.R;
|
//import com.ruoyi.common.core.domain.R;
|
||||||
import com.ruoyi.common.core.utils.ServletUtils;
|
//import com.ruoyi.common.core.utils.ServletUtils;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
//import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.common.redis.service.RedisService;
|
//import com.ruoyi.common.redis.service.RedisService;
|
||||||
import com.ruoyi.gateway.config.properties.IgnoreWhiteProperties;
|
//import com.ruoyi.gateway.config.properties.IgnoreWhiteProperties;
|
||||||
import reactor.core.publisher.Mono;
|
//import reactor.core.publisher.Mono;
|
||||||
|
//
|
||||||
/**
|
///**
|
||||||
* 网关鉴权
|
// * 网关鉴权
|
||||||
*
|
// *
|
||||||
* @author ruoyi
|
// * @author ruoyi
|
||||||
*/
|
// */
|
||||||
@Component
|
//@Component
|
||||||
public class AuthFilter implements GlobalFilter, Ordered
|
//public class AuthFilter implements GlobalFilter, Ordered
|
||||||
{
|
//{
|
||||||
private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
|
// private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
|
||||||
|
//
|
||||||
private final static long EXPIRE_TIME = Constants.TOKEN_EXPIRE * 60;
|
// private final static long EXPIRE_TIME = Constants.TOKEN_EXPIRE * 60;
|
||||||
|
//
|
||||||
// 排除过滤的 uri 地址,nacos自行添加
|
// // 排除过滤的 uri 地址,nacos自行添加
|
||||||
@Autowired
|
// @Autowired
|
||||||
private IgnoreWhiteProperties ignoreWhite;
|
// private IgnoreWhiteProperties ignoreWhite;
|
||||||
|
//
|
||||||
@Resource(name = "stringRedisTemplate")
|
// @Resource(name = "stringRedisTemplate")
|
||||||
private ValueOperations<String, String> sops;
|
// private ValueOperations<String, String> sops;
|
||||||
|
//
|
||||||
@Autowired
|
// @Autowired
|
||||||
private RedisService redisService;
|
// private RedisService redisService;
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
|
// public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
|
||||||
{
|
// {
|
||||||
String url = exchange.getRequest().getURI().getPath();
|
// String url = exchange.getRequest().getURI().getPath();
|
||||||
// 跳过不需要验证的路径
|
// // 跳过不需要验证的路径
|
||||||
if (StringUtils.matches(url, ignoreWhite.getWhites()))
|
// if (StringUtils.matches(url, ignoreWhite.getWhites()))
|
||||||
{
|
// {
|
||||||
return chain.filter(exchange);
|
// return chain.filter(exchange);
|
||||||
}
|
// }
|
||||||
String token = getToken(exchange.getRequest());
|
// String token = getToken(exchange.getRequest());
|
||||||
if (StringUtils.isBlank(token))
|
// if (StringUtils.isBlank(token))
|
||||||
{
|
// {
|
||||||
return setUnauthorizedResponse(exchange, "令牌不能为空");
|
// return setUnauthorizedResponse(exchange, "令牌不能为空");
|
||||||
}
|
// }
|
||||||
String userStr = sops.get(getTokenKey(token));
|
// String userStr = sops.get(getTokenKey(token));
|
||||||
if (StringUtils.isNull(userStr))
|
// if (StringUtils.isNull(userStr))
|
||||||
{
|
// {
|
||||||
return setUnauthorizedResponse(exchange, "登录状态已过期");
|
// return setUnauthorizedResponse(exchange, "登录状态已过期");
|
||||||
}
|
// }
|
||||||
JSONObject obj = JSONObject.parseObject(userStr);
|
// JSONObject obj = JSONObject.parseObject(userStr);
|
||||||
String userid = obj.getString("userid");
|
// String userid = obj.getString("userid");
|
||||||
String username = obj.getString("username");
|
// String username = obj.getString("username");
|
||||||
if (StringUtils.isBlank(userid) || StringUtils.isBlank(username))
|
// if (StringUtils.isBlank(userid) || StringUtils.isBlank(username))
|
||||||
{
|
// {
|
||||||
return setUnauthorizedResponse(exchange, "令牌验证失败");
|
// return setUnauthorizedResponse(exchange, "令牌验证失败");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// 设置过期时间
|
// // 设置过期时间
|
||||||
redisService.expire(getTokenKey(token), EXPIRE_TIME);
|
// redisService.expire(getTokenKey(token), EXPIRE_TIME);
|
||||||
// 设置用户信息到请求
|
// // 设置用户信息到请求
|
||||||
ServerHttpRequest mutableReq = exchange.getRequest().mutate().header(CacheConstants.DETAILS_USER_ID, userid)
|
// ServerHttpRequest mutableReq = exchange.getRequest().mutate().header(CacheConstants.DETAILS_USER_ID, userid)
|
||||||
.header(CacheConstants.DETAILS_USERNAME, ServletUtils.urlEncode(username)).build();
|
// .header(CacheConstants.DETAILS_USERNAME, ServletUtils.urlEncode(username)).build();
|
||||||
ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
|
// ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
|
||||||
|
//
|
||||||
return chain.filter(mutableExchange);
|
// return chain.filter(mutableExchange);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private Mono<Void> setUnauthorizedResponse(ServerWebExchange exchange, String msg)
|
// private Mono<Void> setUnauthorizedResponse(ServerWebExchange exchange, String msg)
|
||||||
{
|
// {
|
||||||
ServerHttpResponse response = exchange.getResponse();
|
// ServerHttpResponse response = exchange.getResponse();
|
||||||
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
// response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||||
response.setStatusCode(HttpStatus.OK);
|
// response.setStatusCode(HttpStatus.OK);
|
||||||
|
//
|
||||||
log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
|
// log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
|
||||||
|
//
|
||||||
return response.writeWith(Mono.fromSupplier(() -> {
|
// return response.writeWith(Mono.fromSupplier(() -> {
|
||||||
DataBufferFactory bufferFactory = response.bufferFactory();
|
// DataBufferFactory bufferFactory = response.bufferFactory();
|
||||||
return bufferFactory.wrap(JSON.toJSONBytes(R.fail(msg)));
|
// return bufferFactory.wrap(JSON.toJSONBytes(R.fail(msg)));
|
||||||
}));
|
// }));
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private String getTokenKey(String token)
|
// private String getTokenKey(String token)
|
||||||
{
|
// {
|
||||||
return CacheConstants.LOGIN_TOKEN_KEY + token;
|
// return CacheConstants.LOGIN_TOKEN_KEY + token;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 获取请求token
|
// * 获取请求token
|
||||||
*/
|
// */
|
||||||
private String getToken(ServerHttpRequest request)
|
// private String getToken(ServerHttpRequest request)
|
||||||
{
|
// {
|
||||||
String token = request.getHeaders().getFirst(CacheConstants.HEADER);
|
// String token = request.getHeaders().getFirst(CacheConstants.HEADER);
|
||||||
if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX))
|
// if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX))
|
||||||
{
|
// {
|
||||||
token = token.replace(CacheConstants.TOKEN_PREFIX, "");
|
// token = token.replace(CacheConstants.TOKEN_PREFIX, "");
|
||||||
}
|
// }
|
||||||
return token;
|
// return token;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public int getOrder()
|
// public int getOrder()
|
||||||
{
|
// {
|
||||||
return -200;
|
// return -200;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
@ -16,14 +16,15 @@ spring:
|
||||||
nacos:
|
nacos:
|
||||||
discovery:
|
discovery:
|
||||||
# 服务注册地址
|
# 服务注册地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
config:
|
config:
|
||||||
# 配置中心地址
|
# 配置中心地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
# 配置文件格式
|
# 配置文件格式
|
||||||
file-extension: yml
|
file-extension: yml
|
||||||
# 共享配置
|
# 共享配置
|
||||||
shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
shared-configs:
|
||||||
|
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
||||||
sentinel:
|
sentinel:
|
||||||
# 取消控制台懒加载
|
# 取消控制台懒加载
|
||||||
eager: true
|
eager: true
|
||||||
|
|
@ -34,7 +35,7 @@ spring:
|
||||||
datasource:
|
datasource:
|
||||||
ds1:
|
ds1:
|
||||||
nacos:
|
nacos:
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
dataId: sentinel-ruoyi-gateway
|
dataId: sentinel-ruoyi-gateway
|
||||||
groupId: DEFAULT_GROUP
|
groupId: DEFAULT_GROUP
|
||||||
data-type: json
|
data-type: json
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,12 @@ spring:
|
||||||
nacos:
|
nacos:
|
||||||
discovery:
|
discovery:
|
||||||
# 服务注册地址
|
# 服务注册地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
config:
|
config:
|
||||||
# 配置中心地址
|
# 配置中心地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
# 配置文件格式
|
# 配置文件格式
|
||||||
file-extension: yml
|
file-extension: yml
|
||||||
# 共享配置
|
# 共享配置
|
||||||
shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
shared-configs:
|
||||||
|
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
||||||
|
|
@ -25,7 +25,7 @@ import com.ruoyi.common.core.constant.Constants;
|
||||||
import com.ruoyi.common.core.constant.GenConstants;
|
import com.ruoyi.common.core.constant.GenConstants;
|
||||||
import com.ruoyi.common.core.exception.CustomException;
|
import com.ruoyi.common.core.exception.CustomException;
|
||||||
import com.ruoyi.common.core.text.CharsetKit;
|
import com.ruoyi.common.core.text.CharsetKit;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.common.core.utils.file.FileUtils;
|
import com.ruoyi.common.core.utils.file.FileUtils;
|
||||||
import com.ruoyi.gen.domain.GenTable;
|
import com.ruoyi.gen.domain.GenTable;
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,12 @@ spring:
|
||||||
nacos:
|
nacos:
|
||||||
discovery:
|
discovery:
|
||||||
# 服务注册地址
|
# 服务注册地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
config:
|
config:
|
||||||
# 配置中心地址
|
# 配置中心地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
# 配置文件格式
|
# 配置文件格式
|
||||||
file-extension: yml
|
file-extension: yml
|
||||||
# 共享配置
|
# 共享配置
|
||||||
shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
shared-configs:
|
||||||
|
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.core.exception.job.TaskException;
|
import com.ruoyi.common.core.exception.job.TaskException;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
import com.ruoyi.common.core.web.controller.BaseController;
|
||||||
import com.ruoyi.common.core.web.domain.AjaxResult;
|
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,12 @@ spring:
|
||||||
nacos:
|
nacos:
|
||||||
discovery:
|
discovery:
|
||||||
# 服务注册地址
|
# 服务注册地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
config:
|
config:
|
||||||
# 配置中心地址
|
# 配置中心地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
# 配置文件格式
|
# 配置文件格式
|
||||||
file-extension: yml
|
file-extension: yml
|
||||||
# 共享配置
|
# 共享配置
|
||||||
shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
shared-configs:
|
||||||
|
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,33 @@
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- SpringCloud Ailibaba Nacos -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- SpringCloud Ailibaba Nacos Config -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- SpringBoot Actuator -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- RuoYi Api System -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-api-system</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.csp</groupId>
|
<groupId>com.alibaba.csp</groupId>
|
||||||
<artifactId>sentinel-core</artifactId>
|
<artifactId>sentinel-core</artifactId>
|
||||||
|
|
@ -145,6 +172,10 @@
|
||||||
<version>1.16.1</version>
|
<version>1.16.1</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>com.ruoyi</groupId>-->
|
||||||
|
<!-- <artifactId>ruoyi-common-security</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,20 @@ package com.alibaba.csp.sentinel.dashboard;
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.init.InitExecutor;
|
import com.alibaba.csp.sentinel.init.InitExecutor;
|
||||||
|
|
||||||
|
//import com.ruoyi.common.security.annotation.EnableCustomConfig;
|
||||||
|
//import com.ruoyi.common.security.annotation.EnableRyFeignClients;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sentinel dashboard application.
|
* Sentinel dashboard application.
|
||||||
*
|
*
|
||||||
* @author Carpenter Lee
|
* @author Carpenter Lee
|
||||||
*/
|
*/
|
||||||
@SpringBootApplication
|
//@EnableCustomConfig
|
||||||
|
//@EnableRyFeignClients
|
||||||
|
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
|
||||||
public class RuoYiSentinelDashboardApplication {
|
public class RuoYiSentinelDashboardApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,8 @@ public class WebConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(WebConfig.class);
|
private final Logger logger = LoggerFactory.getLogger(WebConfig.class);
|
||||||
|
|
||||||
@Autowired
|
// @Autowired
|
||||||
private LoginAuthenticationFilter loginAuthenticationFilter;
|
// private LoginAuthenticationFilter loginAuthenticationFilter;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AuthorizationInterceptor authorizationInterceptor;
|
private AuthorizationInterceptor authorizationInterceptor;
|
||||||
|
|
@ -104,13 +104,13 @@ public class WebConfig implements WebMvcConfigurer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
// @Bean
|
||||||
public FilterRegistrationBean authenticationFilterRegistration() {
|
// public FilterRegistrationBean authenticationFilterRegistration() {
|
||||||
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
|
// FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
|
||||||
registration.setFilter(loginAuthenticationFilter);
|
// registration.setFilter(loginAuthenticationFilter);
|
||||||
registration.addUrlPatterns("/*");
|
// registration.addUrlPatterns("/*");
|
||||||
registration.setName("authenticationFilter");
|
// registration.setName("authenticationFilter");
|
||||||
registration.setOrder(0);
|
// registration.setOrder(0);
|
||||||
return registration;
|
// return registration;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.alibaba.csp.sentinel.dashboard.controller.v2;
|
||||||
|
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 控制器基类
|
||||||
|
* @author alikes
|
||||||
|
*/
|
||||||
|
public class BaseController {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,14 +19,13 @@ import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
|
import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
|
||||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
|
|
||||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
|
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
|
||||||
import com.alibaba.csp.sentinel.util.StringUtil;
|
import com.alibaba.csp.sentinel.util.StringUtil;
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
|
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
|
||||||
import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemoryRuleRepositoryAdapter;
|
import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemoryRuleRepositoryAdapter;
|
||||||
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
|
|
||||||
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
|
|
||||||
import com.alibaba.csp.sentinel.dashboard.domain.Result;
|
import com.alibaba.csp.sentinel.dashboard.domain.Result;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
@ -51,7 +50,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(value = "/v2/flow")
|
@RequestMapping(value = "/v2/flow")
|
||||||
public class FlowControllerV2 {
|
public class FlowControllerV2 extends BaseController {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class);
|
private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.alibaba.csp.sentinel.dashboard.rule.nacos;
|
||||||
|
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
|
||||||
|
import com.alibaba.csp.sentinel.datasource.Converter;
|
||||||
|
import com.alibaba.csp.sentinel.util.StringUtil;
|
||||||
|
import com.alibaba.nacos.api.config.ConfigService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 降级规则
|
||||||
|
* @author alikes
|
||||||
|
*/
|
||||||
|
@Component("degradeRuleNacosProvider")
|
||||||
|
public class DegradeRuleNacosProvider implements DynamicRuleProvider<List<DegradeRuleEntity>> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigService configService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Converter<String, List<DegradeRuleEntity>> converter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DegradeRuleEntity> getRules(String appName) throws Exception {
|
||||||
|
String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
|
||||||
|
NacosConfigUtil.GROUP_ID, 3000);
|
||||||
|
if (StringUtil.isEmpty(rules)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return converter.convert(rules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.alibaba.csp.sentinel.dashboard.rule.nacos;
|
||||||
|
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
|
||||||
|
import com.alibaba.csp.sentinel.datasource.Converter;
|
||||||
|
import com.alibaba.csp.sentinel.util.AssertUtil;
|
||||||
|
import com.alibaba.nacos.api.config.ConfigService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Eric Zhao
|
||||||
|
* @since 1.4.0
|
||||||
|
*/
|
||||||
|
@Component("degradeRuleNacosPublisher")
|
||||||
|
public class DegradeRuleNacosPublisher implements DynamicRulePublisher<List<DegradeRuleEntity>> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigService configService;
|
||||||
|
@Autowired
|
||||||
|
private Converter<List<DegradeRuleEntity>, String> converter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publish(String app, List<DegradeRuleEntity> rules) throws Exception {
|
||||||
|
AssertUtil.notEmpty(app, "app name cannot be empty");
|
||||||
|
if (rules == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
|
||||||
|
NacosConfigUtil.GROUP_ID, converter.convert(rules));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package com.alibaba.csp.sentinel.dashboard.rule.nacos;
|
package com.alibaba.csp.sentinel.dashboard.rule.nacos;
|
||||||
|
|
||||||
|
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
|
||||||
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
|
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
|
||||||
import com.alibaba.csp.sentinel.datasource.Converter;
|
import com.alibaba.csp.sentinel.datasource.Converter;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
|
@ -36,7 +37,7 @@ import java.util.Properties;
|
||||||
@Configuration
|
@Configuration
|
||||||
public class NacosConfig {
|
public class NacosConfig {
|
||||||
|
|
||||||
@Value("${spring.nacos.server-addr}")
|
@Value("${spring.cloud.nacos.config.server-addr}")
|
||||||
private String serverAddr;
|
private String serverAddr;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|
@ -49,6 +50,16 @@ public class NacosConfig {
|
||||||
return s -> JSON.parseArray(s, FlowRuleEntity.class);
|
return s -> JSON.parseArray(s, FlowRuleEntity.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Converter<List<DegradeRuleEntity>, String> degradeRuleEntityEncoder() {
|
||||||
|
return JSON::toJSONString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Converter<String, List<DegradeRuleEntity>> degradeRuleEntityDecoder() {
|
||||||
|
return s -> JSON.parseArray(s, DegradeRuleEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ConfigService nacosConfigService() throws Exception {
|
public ConfigService nacosConfigService() throws Exception {
|
||||||
if(StringUtils.isEmpty(serverAddr)){//不配置时,使用默认配置
|
if(StringUtils.isEmpty(serverAddr)){//不配置时,使用默认配置
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#spring settings
|
|
||||||
spring.http.encoding.force=true
|
|
||||||
spring.http.encoding.charset=UTF-8
|
|
||||||
spring.http.encoding.enabled=true
|
|
||||||
|
|
||||||
#cookie name setting
|
|
||||||
server.servlet.session.cookie.name=sentinel_dashboard_cookie
|
|
||||||
|
|
||||||
#logging settings
|
|
||||||
logging.level.org.springframework.web=INFO
|
|
||||||
logging.file=${user.home}/logs/csp/sentinel-dashboard.log
|
|
||||||
logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
|
|
||||||
#logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
|
|
||||||
|
|
||||||
#auth settings
|
|
||||||
auth.filter.exclude-urls=/,/auth/login,/auth/logout,/registry/machine,/version
|
|
||||||
auth.filter.exclude-url-suffixes=htm,html,js,css,map,ico,ttf,woff,png
|
|
||||||
# If auth.enabled=false, Sentinel console disable login
|
|
||||||
auth.username=sentinel
|
|
||||||
auth.password=sentinel
|
|
||||||
|
|
||||||
# Inject the dashboard version. It's required to enable
|
|
||||||
# filtering in pom.xml for this resource file.
|
|
||||||
sentinel.dashboard.version=${project.version}
|
|
||||||
spring.nacos.server-addr=127.0.0.1:8848
|
|
||||||
server.port=8718
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
## Tomcat
|
||||||
|
#server:
|
||||||
|
# port: 8718
|
||||||
|
# servlet:
|
||||||
|
# encoding:
|
||||||
|
# enabled: true
|
||||||
|
# force: true
|
||||||
|
# charset: UTF-8
|
||||||
|
# session:
|
||||||
|
# cookie:
|
||||||
|
# name: sentinel_dashboard_cookie
|
||||||
|
#logging:
|
||||||
|
# level:
|
||||||
|
# org:
|
||||||
|
# springframework:
|
||||||
|
# web: INFO
|
||||||
|
# file:
|
||||||
|
# name: ${user.home}/logs/csp/sentinel-dashboard.log
|
||||||
|
# pattern:
|
||||||
|
# file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
|
||||||
|
#auth:
|
||||||
|
# filter:
|
||||||
|
# exclude-urls: "/,/auth/login,/auth/logout,/registry/machine,/version"
|
||||||
|
# exclude-url-suffixes: "htm,html,js,css,map,ico,ttf,woff,png"
|
||||||
|
# username: sentinel
|
||||||
|
# password: sentinel
|
||||||
|
#sentinel:
|
||||||
|
# dashboard:
|
||||||
|
# version: ${project.version}
|
||||||
|
## Spring
|
||||||
|
#spring:
|
||||||
|
# application:
|
||||||
|
# # 应用名称
|
||||||
|
# name: ruoyi-sentinel
|
||||||
|
# profiles:
|
||||||
|
# # 环境配置
|
||||||
|
# active: dev
|
||||||
|
# cloud:
|
||||||
|
# nacos:
|
||||||
|
# discovery:
|
||||||
|
# # 服务注册地址
|
||||||
|
# server-addr: 175.25.50.135:8848
|
||||||
|
# config:
|
||||||
|
# # 配置中心地址
|
||||||
|
# server-addr: 175.25.50.135:8848
|
||||||
|
# # 配置文件格式
|
||||||
|
# file-extension: yml
|
||||||
|
# # 共享配置
|
||||||
|
# shared-configs:
|
||||||
|
# - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
sentinel:
|
||||||
|
dashboard:
|
||||||
|
version: ${project.version}
|
||||||
|
# Spring
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
# 应用名称
|
||||||
|
name: ruoyi-sentinel
|
||||||
|
profiles:
|
||||||
|
# 环境配置
|
||||||
|
active: dev
|
||||||
|
cloud:
|
||||||
|
nacos:
|
||||||
|
discovery:
|
||||||
|
# 服务注册地址
|
||||||
|
server-addr: 175.25.50.135:8848
|
||||||
|
config:
|
||||||
|
# 配置中心地址
|
||||||
|
server-addr: 175.25.50.135:8848
|
||||||
|
# 配置文件格式
|
||||||
|
file-extension: yml
|
||||||
|
# 共享配置
|
||||||
|
shared-configs:
|
||||||
|
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
||||||
|
|
@ -0,0 +1,204 @@
|
||||||
|
var app = angular.module('sentinelDashboardApp');
|
||||||
|
|
||||||
|
app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDialog', 'MachineService',
|
||||||
|
function ($scope, $stateParams, DegradeService, ngDialog, MachineService) {
|
||||||
|
//初始化
|
||||||
|
$scope.app = $stateParams.app;
|
||||||
|
$scope.rulesPageConfig = {
|
||||||
|
pageSize: 10,
|
||||||
|
currentPageIndex: 1,
|
||||||
|
totalPage: 1,
|
||||||
|
totalCount: 0,
|
||||||
|
};
|
||||||
|
$scope.macsInputConfig = {
|
||||||
|
searchField: ['text', 'value'],
|
||||||
|
persist: true,
|
||||||
|
create: false,
|
||||||
|
maxItems: 1,
|
||||||
|
render: {
|
||||||
|
item: function (data, escape) {
|
||||||
|
return '<div>' + escape(data.text) + '</div>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onChange: function (value, oldValue) {
|
||||||
|
$scope.macInputModel = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
getMachineRules();
|
||||||
|
function getMachineRules() {
|
||||||
|
if (!$scope.macInputModel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var mac = $scope.macInputModel.split(':');
|
||||||
|
DegradeService.queryMachineRules($scope.app, mac[0], mac[1]).success(
|
||||||
|
function (data) {
|
||||||
|
if (data.code == 0 && data.data) {
|
||||||
|
$scope.rules = data.data;
|
||||||
|
$scope.rulesPageConfig.totalCount = $scope.rules.length;
|
||||||
|
} else {
|
||||||
|
$scope.rules = [];
|
||||||
|
$scope.rulesPageConfig.totalCount = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
$scope.getMachineRules = getMachineRules;
|
||||||
|
|
||||||
|
var degradeRuleDialog;
|
||||||
|
$scope.editRule = function (rule) {
|
||||||
|
$scope.currentRule = angular.copy(rule);
|
||||||
|
$scope.degradeRuleDialog = {
|
||||||
|
title: '编辑降级规则',
|
||||||
|
type: 'edit',
|
||||||
|
confirmBtnText: '保存'
|
||||||
|
};
|
||||||
|
degradeRuleDialog = ngDialog.open({
|
||||||
|
template: '/app/views/dialog/degrade-rule-dialog.html',
|
||||||
|
width: 680,
|
||||||
|
overlay: true,
|
||||||
|
scope: $scope
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.addNewRule = function () {
|
||||||
|
var mac = $scope.macInputModel.split(':');
|
||||||
|
$scope.currentRule = {
|
||||||
|
grade: 0,
|
||||||
|
app: $scope.app,
|
||||||
|
ip: mac[0],
|
||||||
|
port: mac[1],
|
||||||
|
limitApp: 'default',
|
||||||
|
minRequestAmount: 5,
|
||||||
|
statIntervalMs: 1000,
|
||||||
|
};
|
||||||
|
$scope.degradeRuleDialog = {
|
||||||
|
title: '新增降级规则',
|
||||||
|
type: 'add',
|
||||||
|
confirmBtnText: '新增'
|
||||||
|
};
|
||||||
|
degradeRuleDialog = ngDialog.open({
|
||||||
|
template: '/app/views/dialog/degrade-rule-dialog.html',
|
||||||
|
width: 680,
|
||||||
|
overlay: true,
|
||||||
|
scope: $scope
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.saveRule = function () {
|
||||||
|
if (!DegradeService.checkRuleValid($scope.currentRule)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($scope.degradeRuleDialog.type === 'add') {
|
||||||
|
addNewRule($scope.currentRule);
|
||||||
|
} else if ($scope.degradeRuleDialog.type === 'edit') {
|
||||||
|
saveRule($scope.currentRule, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseDegradeMode(grade) {
|
||||||
|
switch (grade) {
|
||||||
|
case 0:
|
||||||
|
return '慢调用比例';
|
||||||
|
case 1:
|
||||||
|
return '异常比例';
|
||||||
|
case 2:
|
||||||
|
return '异常数';
|
||||||
|
default:
|
||||||
|
return '未知';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var confirmDialog;
|
||||||
|
$scope.deleteRule = function (rule) {
|
||||||
|
$scope.currentRule = rule;
|
||||||
|
$scope.confirmDialog = {
|
||||||
|
title: '删除降级规则',
|
||||||
|
type: 'delete_rule',
|
||||||
|
attentionTitle: '请确认是否删除如下降级规则',
|
||||||
|
attention: '资源名: ' + rule.resource +
|
||||||
|
', 降级模式: ' + parseDegradeMode(rule.grade) + ', 阈值: ' + rule.count,
|
||||||
|
confirmBtnText: '删除',
|
||||||
|
};
|
||||||
|
confirmDialog = ngDialog.open({
|
||||||
|
template: '/app/views/dialog/confirm-dialog.html',
|
||||||
|
scope: $scope,
|
||||||
|
overlay: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.confirm = function () {
|
||||||
|
if ($scope.confirmDialog.type == 'delete_rule') {
|
||||||
|
deleteRule($scope.currentRule);
|
||||||
|
} else {
|
||||||
|
console.error('error');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function deleteRule(rule) {
|
||||||
|
DegradeService.deleteRule(rule).success(function (data) {
|
||||||
|
if (data.code == 0) {
|
||||||
|
getMachineRules();
|
||||||
|
confirmDialog.close();
|
||||||
|
} else {
|
||||||
|
alert('失败:' + data.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function addNewRule(rule) {
|
||||||
|
DegradeService.newRule(rule).success(function (data) {
|
||||||
|
if (data.code == 0) {
|
||||||
|
getMachineRules();
|
||||||
|
degradeRuleDialog.close();
|
||||||
|
} else {
|
||||||
|
alert('失败:' + data.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function saveRule(rule, edit) {
|
||||||
|
DegradeService.saveRule(rule).success(function (data) {
|
||||||
|
if (data.code == 0) {
|
||||||
|
getMachineRules();
|
||||||
|
if (edit) {
|
||||||
|
degradeRuleDialog.close();
|
||||||
|
} else {
|
||||||
|
confirmDialog.close();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert('失败:' + data.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
queryAppMachines();
|
||||||
|
function queryAppMachines() {
|
||||||
|
MachineService.getAppMachines($scope.app).success(
|
||||||
|
function (data) {
|
||||||
|
if (data.code == 0) {
|
||||||
|
// $scope.machines = data.data;
|
||||||
|
if (data.data) {
|
||||||
|
$scope.machines = [];
|
||||||
|
$scope.macsInputOptions = [];
|
||||||
|
data.data.forEach(function (item) {
|
||||||
|
if (item.healthy) {
|
||||||
|
$scope.macsInputOptions.push({
|
||||||
|
text: item.ip + ':' + item.port,
|
||||||
|
value: item.ip + ':' + item.port
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if ($scope.macsInputOptions.length > 0) {
|
||||||
|
$scope.macInputModel = $scope.macsInputOptions[0].value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$scope.macsInputOptions = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
$scope.$watch('macInputModel', function () {
|
||||||
|
if ($scope.macInputModel) {
|
||||||
|
getMachineRules();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}]);
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
var app = angular.module('sentinelDashboardApp');
|
||||||
|
|
||||||
|
app.service('DegradeService', ['$http', function ($http) {
|
||||||
|
this.queryMachineRules = function (app, ip, port) {
|
||||||
|
var param = {
|
||||||
|
app: app,
|
||||||
|
ip: ip,
|
||||||
|
port: port
|
||||||
|
};
|
||||||
|
return $http({
|
||||||
|
url: '/V2/degrade/rules',
|
||||||
|
params: param,
|
||||||
|
method: 'GET'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.newRule = function (rule) {
|
||||||
|
return $http({
|
||||||
|
url: '/degrade/rule',
|
||||||
|
data: rule,
|
||||||
|
method: 'POST'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.saveRule = function (rule) {
|
||||||
|
var param = {
|
||||||
|
id: rule.id,
|
||||||
|
resource: rule.resource,
|
||||||
|
limitApp: rule.limitApp,
|
||||||
|
grade: rule.grade,
|
||||||
|
count: rule.count,
|
||||||
|
timeWindow: rule.timeWindow,
|
||||||
|
statIntervalMs: rule.statIntervalMs,
|
||||||
|
minRequestAmount: rule.minRequestAmount,
|
||||||
|
slowRatioThreshold: rule.slowRatioThreshold,
|
||||||
|
};
|
||||||
|
return $http({
|
||||||
|
url: '/degrade/rule/' + rule.id,
|
||||||
|
data: param,
|
||||||
|
method: 'PUT'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.deleteRule = function (rule) {
|
||||||
|
return $http({
|
||||||
|
url: '/degrade/rule/' + rule.id,
|
||||||
|
method: 'DELETE'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.checkRuleValid = function (rule) {
|
||||||
|
if (rule.resource === undefined || rule.resource === '') {
|
||||||
|
alert('资源名称不能为空');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rule.grade === undefined || rule.grade < 0) {
|
||||||
|
alert('未知的降级策略');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rule.count === undefined || rule.count === '' || rule.count < 0) {
|
||||||
|
alert('降级阈值不能为空或小于 0');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rule.timeWindow == undefined || rule.timeWindow === '' || rule.timeWindow <= 0) {
|
||||||
|
alert('熔断时长必须大于 0s');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rule.minRequestAmount == undefined || rule.minRequestAmount <= 0) {
|
||||||
|
alert('最小请求数目需大于 0');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rule.statIntervalMs == undefined || rule.statIntervalMs <= 0) {
|
||||||
|
alert('统计窗口时长需大于 0s');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rule.statIntervalMs !== undefined && rule.statIntervalMs > 60 * 1000 * 2) {
|
||||||
|
alert('统计窗口时长不能超过 120 分钟');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 异常比率类型.
|
||||||
|
if (rule.grade == 1 && rule.count > 1) {
|
||||||
|
alert('异常比率超出范围:[0.0 - 1.0]');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rule.grade == 0) {
|
||||||
|
if (rule.slowRatioThreshold == undefined) {
|
||||||
|
alert('慢调用比率不能为空');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rule.slowRatioThreshold < 0 || rule.slowRatioThreshold > 1) {
|
||||||
|
alert('慢调用比率超出范围:[0.0 - 1.0]');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}]);
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
<div class="row" style="margin-left: 1px; margin-top:10px; height: 50px;">
|
||||||
|
<div class="col-md-6" style="margin-bottom: 10px;">
|
||||||
|
<span style="font-size: 30px;font-weight: bold;">{{app}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<button class="btn btn-default-inverse" style="float: right; margin-right: 10px;" ng-disabled="!macInputModel" ng-click="addNewRule()">
|
||||||
|
<i class="fa fa-plus"></i> 新增降级规则</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="separator"></div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row" style="margin-top: 20px; margin-bottom: 20px;">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="inputs-header">
|
||||||
|
<span class="brand" style="font-size: 13px;">降级规则</span>
|
||||||
|
<!--<button class="btn btn-danger" style="float: right;margin-right: 10px;height: 30px;font-size: 12px;" ng-click="disableAll()">全部禁用</button>-->
|
||||||
|
<button class="btn btn-primary" style="float: right; margin-right: 10px; height: 30px;font-size: 12px;" ng-click="getMachineRules()">刷新</button>
|
||||||
|
<input class="form-control witdh-200" placeholder="关键字" ng-model="searchKey">
|
||||||
|
<div class="control-group" style="float:right;margin-right: 10px;margin-bottom: -10px;">
|
||||||
|
<selectize id="gsInput" class="selectize-input-200" config="macsInputConfig" options="macsInputOptions" ng-model="macInputModel"
|
||||||
|
placeholder="机器"></selectize>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--.tools-header -->
|
||||||
|
<div class="card-body" style="padding: 0px 0px;">
|
||||||
|
<table class="table" style="border-left: none; border-right:none;margin-top: 10px;">
|
||||||
|
<thead>
|
||||||
|
<tr style="background: #F3F5F7;">
|
||||||
|
<td style="width: 40%">
|
||||||
|
资源名
|
||||||
|
</td>
|
||||||
|
<td style="width: 10%;">
|
||||||
|
降级策略
|
||||||
|
</td>
|
||||||
|
<td style="width: 10%;">
|
||||||
|
阈值
|
||||||
|
</td>
|
||||||
|
<td style="width: 10%;">
|
||||||
|
熔断时长(s)
|
||||||
|
</td>
|
||||||
|
<td style="width: 12%;">
|
||||||
|
操作
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr dir-paginate="rule in rules | filter : searchKey | itemsPerPage: rulesPageConfig.pageSize " current-page="rulesPageConfig.currentPageIndex"
|
||||||
|
pagination-id="entriesPagination">
|
||||||
|
<td style="word-wrap:break-word;word-break:break-all;">{{rule.resource}}</td>
|
||||||
|
<!--<td style="word-wrap:break-word;word-break:break-all;">{{rule.limitApp }}</td>-->
|
||||||
|
<td>
|
||||||
|
<span ng-if="rule.grade == 0">慢调用比例</span>
|
||||||
|
<span ng-if="rule.grade == 1" title="异常比例">异常比例</span>
|
||||||
|
<span ng-if="rule.grade == 2" title="异常数">异常数</span>
|
||||||
|
</td>
|
||||||
|
<td style="word-wrap:break-word;word-break:break-all;">
|
||||||
|
{{rule.count}}
|
||||||
|
</td>
|
||||||
|
<td style="word-wrap:break-word;word-break:break-all;">
|
||||||
|
{{rule.timeWindow}}s
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-xs btn-default" type="button" ng-click="editRule(rule)" style="font-size: 12px; height:25px;">编辑</button>
|
||||||
|
<button class="btn btn-xs btn-default" type="button" ng-click="deleteRule(rule)" style="font-size: 12px; height:25px;">删除</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!-- .card-body -->
|
||||||
|
<div class="pagination-footer">
|
||||||
|
<dir-pagination-controls boundary-links="true" template-url="app/views/pagination.tpl.html" pagination-id="entriesPagination"
|
||||||
|
on-page-change="">
|
||||||
|
</dir-pagination-controls>
|
||||||
|
<div class="tools" style="">
|
||||||
|
<span>共 {{rulesPageConfig.totalCount}} 条记录, </span>
|
||||||
|
<span>
|
||||||
|
每页
|
||||||
|
<input class="form-control" ng-model="rulesPageConfig.pageSize"> 条记录,
|
||||||
|
</span>
|
||||||
|
<span>第 {{rulesPageConfig.currentPageIndex}} / {{rulesPageConfig.totalPage}} 页</span>
|
||||||
|
</div>
|
||||||
|
<!-- .tools -->
|
||||||
|
</div>
|
||||||
|
<!-- pagination-footer -->
|
||||||
|
</div>
|
||||||
|
<!-- .card -->
|
||||||
|
</div>
|
||||||
|
<!-- .col-md-12 -->
|
||||||
|
</div>
|
||||||
|
<!-- -->
|
||||||
|
</div>
|
||||||
|
<!-- .container-fluid -->
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.core.constant.UserConstants;
|
import com.ruoyi.common.core.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
import com.ruoyi.common.core.web.controller.BaseController;
|
||||||
import com.ruoyi.common.core.web.domain.AjaxResult;
|
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.core.constant.UserConstants;
|
import com.ruoyi.common.core.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
import com.ruoyi.common.core.web.controller.BaseController;
|
||||||
import com.ruoyi.common.core.web.domain.AjaxResult;
|
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
|
@ -14,7 +16,6 @@ import org.springframework.web.bind.annotation.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
import com.ruoyi.common.core.web.controller.BaseController;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.core.constant.UserConstants;
|
import com.ruoyi.common.core.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
import com.ruoyi.common.core.web.controller.BaseController;
|
||||||
import com.ruoyi.common.core.web.domain.AjaxResult;
|
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.core.constant.Constants;
|
import com.ruoyi.common.core.constant.Constants;
|
||||||
import com.ruoyi.common.core.constant.UserConstants;
|
import com.ruoyi.common.core.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
import com.ruoyi.common.core.web.controller.BaseController;
|
||||||
import com.ruoyi.common.core.web.domain.AjaxResult;
|
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
import com.ruoyi.common.core.web.controller.BaseController;
|
||||||
import com.ruoyi.common.core.web.domain.AjaxResult;
|
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.web.page.TableDataInfo;
|
import com.ruoyi.common.core.web.page.TableDataInfo;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.core.constant.UserConstants;
|
import com.ruoyi.common.core.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
import com.ruoyi.common.core.web.controller.BaseController;
|
||||||
import com.ruoyi.common.core.web.domain.AjaxResult;
|
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.common.core.domain.R;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.utils.ServletUtils;
|
import com.ruoyi.common.core.utils.ServletUtils;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
import com.ruoyi.common.core.web.controller.BaseController;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.core.constant.UserConstants;
|
import com.ruoyi.common.core.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
import com.ruoyi.common.core.web.controller.BaseController;
|
||||||
import com.ruoyi.common.core.web.domain.AjaxResult;
|
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,11 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.system.api.model.UserInfo;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
@ -18,7 +22,6 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import com.ruoyi.common.core.constant.UserConstants;
|
import com.ruoyi.common.core.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.common.core.domain.R;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
import com.ruoyi.common.core.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.common.core.web.controller.BaseController;
|
import com.ruoyi.common.core.web.controller.BaseController;
|
||||||
|
|
@ -101,7 +104,7 @@ public class SysUserController extends BaseController
|
||||||
* 获取当前用户信息
|
* 获取当前用户信息
|
||||||
*/
|
*/
|
||||||
@GetMapping("/info/{username}")
|
@GetMapping("/info/{username}")
|
||||||
public R<LoginUser> info(@PathVariable("username") String username)
|
public R<UserInfo> info(@PathVariable("username") String username)
|
||||||
{
|
{
|
||||||
SysUser sysUser = userService.selectUserByUserName(username);
|
SysUser sysUser = userService.selectUserByUserName(username);
|
||||||
if (StringUtils.isNull(sysUser))
|
if (StringUtils.isNull(sysUser))
|
||||||
|
|
@ -112,7 +115,7 @@ public class SysUserController extends BaseController
|
||||||
Set<String> roles = permissionService.getRolePermission(sysUser.getUserId());
|
Set<String> roles = permissionService.getRolePermission(sysUser.getUserId());
|
||||||
// 权限集合
|
// 权限集合
|
||||||
Set<String> permissions = permissionService.getMenuPermission(sysUser.getUserId());
|
Set<String> permissions = permissionService.getMenuPermission(sysUser.getUserId());
|
||||||
LoginUser sysUserVo = new LoginUser();
|
UserInfo sysUserVo = new UserInfo();
|
||||||
sysUserVo.setSysUser(sysUser);
|
sysUserVo.setSysUser(sysUser);
|
||||||
sysUserVo.setRoles(roles);
|
sysUserVo.setRoles(roles);
|
||||||
sysUserVo.setPermissions(permissions);
|
sysUserVo.setPermissions(permissions);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import java.util.stream.Collectors;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.ruoyi.common.core.constant.UserConstants;
|
import com.ruoyi.common.core.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.system.api.domain.SysRole;
|
import com.ruoyi.system.api.domain.SysRole;
|
||||||
import com.ruoyi.system.api.domain.SysUser;
|
import com.ruoyi.system.api.domain.SysUser;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import com.ruoyi.common.core.constant.UserConstants;
|
import com.ruoyi.common.core.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.exception.CustomException;
|
import com.ruoyi.common.core.exception.CustomException;
|
||||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.common.datascope.annotation.DataScope;
|
import com.ruoyi.common.datascope.annotation.DataScope;
|
||||||
import com.ruoyi.system.api.domain.SysRole;
|
import com.ruoyi.system.api.domain.SysRole;
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,12 @@ spring:
|
||||||
nacos:
|
nacos:
|
||||||
discovery:
|
discovery:
|
||||||
# 服务注册地址
|
# 服务注册地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
config:
|
config:
|
||||||
# 配置中心地址
|
# 配置中心地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
# 配置文件格式
|
# 配置文件格式
|
||||||
file-extension: yml
|
file-extension: yml
|
||||||
# 共享配置
|
# 共享配置
|
||||||
shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
shared-configs:
|
||||||
|
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,64 @@ const client_id = 'web'
|
||||||
const client_secret = '123456'
|
const client_secret = '123456'
|
||||||
const scope = 'server'
|
const scope = 'server'
|
||||||
|
|
||||||
|
// // 登录方法
|
||||||
|
// export function login(username, password, code, uuid) {
|
||||||
|
// return request({
|
||||||
|
// url: '/auth/login',
|
||||||
|
// method: 'post',
|
||||||
|
// data: { username, password, code, uuid }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 刷新方法
|
||||||
|
// export function refreshToken() {
|
||||||
|
// return request({
|
||||||
|
// url: '/auth/refresh',
|
||||||
|
// method: 'post'
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 获取用户详细信息
|
||||||
|
// export function getInfo() {
|
||||||
|
// return request({
|
||||||
|
// url: '/system/user/getInfo',
|
||||||
|
// method: 'get'
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 退出方法
|
||||||
|
// export function logout() {
|
||||||
|
// return request({
|
||||||
|
// url: '/auth/logout',
|
||||||
|
// method: 'delete'
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 获取验证码
|
||||||
|
// export function getCodeImg() {
|
||||||
|
// return request({
|
||||||
|
// url: '/code',
|
||||||
|
// method: 'get'
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
// 登录方法
|
// 登录方法
|
||||||
export function login(username, password, code, uuid) {
|
export function login(username, password, code, uuid) {
|
||||||
|
const grant_type = 'password'
|
||||||
return request({
|
return request({
|
||||||
url: '/auth/login',
|
url: '/auth/oauth/token',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: { username, password, code, uuid }
|
params: { username, password, code, uuid, client_id, client_secret, grant_type, scope }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新方法
|
// 刷新方法
|
||||||
export function refreshToken() {
|
export function refreshToken(refresh_token) {
|
||||||
|
const grant_type = 'refresh_token'
|
||||||
return request({
|
return request({
|
||||||
url: '/auth/refresh',
|
url: '/auth/oauth/token',
|
||||||
method: 'post'
|
method: 'post',
|
||||||
|
params: { client_id, client_secret, grant_type, scope, refresh_token }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,7 +76,7 @@ export function getInfo() {
|
||||||
// 退出方法
|
// 退出方法
|
||||||
export function logout() {
|
export function logout() {
|
||||||
return request({
|
return request({
|
||||||
url: '/auth/logout',
|
url: '/auth/token/logout',
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import { login, logout, getInfo, refreshToken } from '@/api/login'
|
import { login, logout, getInfo, refreshToken } from '@/api/login'
|
||||||
import { getToken, setToken, setExpiresIn, removeToken } from '@/utils/auth'
|
import { getToken, setToken,getRefreshToken, setRefreshToken, setExpiresIn, removeToken } from '@/utils/auth'
|
||||||
|
|
||||||
const user = {
|
const user = {
|
||||||
state: {
|
state: {
|
||||||
token: getToken(),
|
token: getToken(),
|
||||||
|
refresh_token: getRefreshToken(),
|
||||||
name: '',
|
name: '',
|
||||||
avatar: '',
|
avatar: '',
|
||||||
roles: [],
|
roles: [],
|
||||||
|
|
@ -17,6 +18,9 @@ const user = {
|
||||||
SET_EXPIRES_IN: (state, time) => {
|
SET_EXPIRES_IN: (state, time) => {
|
||||||
state.expires_in = time
|
state.expires_in = time
|
||||||
},
|
},
|
||||||
|
SET_REFRESH_TOKEN: (state, token) => {
|
||||||
|
state.refresh_token = token
|
||||||
|
},
|
||||||
SET_NAME: (state, name) => {
|
SET_NAME: (state, name) => {
|
||||||
state.name = name
|
state.name = name
|
||||||
},
|
},
|
||||||
|
|
@ -32,6 +36,25 @@ const user = {
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
// // 登录
|
||||||
|
// Login({ commit }, userInfo) {
|
||||||
|
// const username = userInfo.username.trim()
|
||||||
|
// const password = userInfo.password
|
||||||
|
// const code = userInfo.code
|
||||||
|
// const uuid = userInfo.uuid
|
||||||
|
// return new Promise((resolve, reject) => {
|
||||||
|
// login(username, password, code, uuid).then(res => {
|
||||||
|
// let data = res.data
|
||||||
|
// setToken(data.access_token)
|
||||||
|
// commit('SET_TOKEN', data.access_token)
|
||||||
|
// setExpiresIn(data.expires_in)
|
||||||
|
// commit('SET_EXPIRES_IN', data.expires_in)
|
||||||
|
// resolve()
|
||||||
|
// }).catch(error => {
|
||||||
|
// reject(error)
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// },
|
||||||
// 登录
|
// 登录
|
||||||
Login({ commit }, userInfo) {
|
Login({ commit }, userInfo) {
|
||||||
const username = userInfo.username.trim()
|
const username = userInfo.username.trim()
|
||||||
|
|
@ -40,11 +63,12 @@ const user = {
|
||||||
const uuid = userInfo.uuid
|
const uuid = userInfo.uuid
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
login(username, password, code, uuid).then(res => {
|
login(username, password, code, uuid).then(res => {
|
||||||
let data = res.data
|
setToken(res.access_token)
|
||||||
setToken(data.access_token)
|
commit('SET_TOKEN', res.access_token)
|
||||||
commit('SET_TOKEN', data.access_token)
|
setRefreshToken(res.refresh_token)
|
||||||
setExpiresIn(data.expires_in)
|
commit('SET_REFRESH_TOKEN', res.refresh_token)
|
||||||
commit('SET_EXPIRES_IN', data.expires_in)
|
setExpiresIn(res.expires_in)
|
||||||
|
commit('SET_EXPIRES_IN', res.expires_in)
|
||||||
resolve()
|
resolve()
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
reject(error)
|
reject(error)
|
||||||
|
|
@ -73,12 +97,29 @@ const user = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// // 刷新token
|
||||||
|
// RefreshToken({commit, state}) {
|
||||||
|
// return new Promise((resolve, reject) => {
|
||||||
|
// refreshToken(state.token).then(res => {
|
||||||
|
// setExpiresIn(res.data)
|
||||||
|
// commit('SET_EXPIRES_IN', res.data)
|
||||||
|
// resolve()
|
||||||
|
// }).catch(error => {
|
||||||
|
// reject(error)
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
|
||||||
// 刷新token
|
// 刷新token
|
||||||
RefreshToken({commit, state}) {
|
RefreshToken({commit, state}) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
refreshToken(state.token).then(res => {
|
refreshToken(state.refresh_token).then(res => {
|
||||||
setExpiresIn(res.data)
|
setToken(res.access_token)
|
||||||
commit('SET_EXPIRES_IN', res.data)
|
commit('SET_TOKEN', res.access_token)
|
||||||
|
setRefreshToken(res.refresh_token)
|
||||||
|
commit('SET_REFRESH_TOKEN', res.refresh_token)
|
||||||
|
setExpiresIn(res.expires_in)
|
||||||
|
commit('SET_EXPIRES_IN', res.expires_in)
|
||||||
resolve()
|
resolve()
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
reject(error)
|
reject(error)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
|
|
||||||
const TokenKey = 'Admin-Token'
|
const TokenKey = 'Admin-Token'
|
||||||
|
const RefreshTokenKey = 'Admin-Refresh-Token'
|
||||||
const ExpiresInKey = 'Admin-Expires-In'
|
const ExpiresInKey = 'Admin-Expires-In'
|
||||||
|
|
||||||
export function getToken() {
|
export function getToken() {
|
||||||
|
|
@ -16,6 +16,18 @@ export function removeToken() {
|
||||||
return Cookies.remove(TokenKey)
|
return Cookies.remove(TokenKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRefreshToken() {
|
||||||
|
return Cookies.get(RefreshTokenKey) || ``
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setRefreshToken(token) {
|
||||||
|
return Cookies.set(RefreshTokenKey, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeRefreshToken() {
|
||||||
|
return Cookies.remove(RefreshTokenKey)
|
||||||
|
}
|
||||||
|
|
||||||
export function getExpiresIn() {
|
export function getExpiresIn() {
|
||||||
return Cookies.get(ExpiresInKey) || -1
|
return Cookies.get(ExpiresInKey) || -1
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,8 +127,9 @@ export default {
|
||||||
Cookies.remove('rememberMe');
|
Cookies.remove('rememberMe');
|
||||||
}
|
}
|
||||||
this.$store.dispatch("Login", this.loginForm).then(() => {
|
this.$store.dispatch("Login", this.loginForm).then(() => {
|
||||||
this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
|
this.$router.push({ path: this.redirect || "/" }).catch((e)=>{console.log(e);});
|
||||||
}).catch(() => {
|
}).catch((e) => {
|
||||||
|
console.log(e);
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.getCode();
|
this.getCode();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,12 @@ spring:
|
||||||
nacos:
|
nacos:
|
||||||
discovery:
|
discovery:
|
||||||
# 服务注册地址
|
# 服务注册地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
config:
|
config:
|
||||||
# 配置中心地址
|
# 配置中心地址
|
||||||
server-addr: 127.0.0.1:8848
|
server-addr: 175.25.50.135:8848
|
||||||
# 配置文件格式
|
# 配置文件格式
|
||||||
file-extension: yml
|
file-extension: yml
|
||||||
# 共享配置
|
# 共享配置
|
||||||
shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
shared-configs:
|
||||||
|
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ insert into config_info(id, data_id, group_id, content, md5, gmt_create, gmt_mod
|
||||||
(2,'ruoyi-gateway-dev.yml','DEFAULT_GROUP','spring:\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n cloud:\r\n gateway:\r\n discovery:\r\n locator:\r\n lowerCaseServiceId: true\r\n enabled: true\r\n routes:\r\n # 认证中心\r\n - id: ruoyi-auth\r\n uri: lb://ruoyi-auth\r\n predicates:\r\n - Path=/auth/**\r\n filters:\r\n # 验证码处理\r\n - CacheRequestFilter\r\n - ValidateCodeFilter\r\n - StripPrefix=1\r\n # 代码生成\r\n - id: ruoyi-gen\r\n uri: lb://ruoyi-gen\r\n predicates:\r\n - Path=/code/**\r\n filters:\r\n - StripPrefix=1\r\n # 定时任务\r\n - id: ruoyi-job\r\n uri: lb://ruoyi-job\r\n predicates:\r\n - Path=/schedule/**\r\n filters:\r\n - StripPrefix=1\r\n # 系统模块\r\n - id: ruoyi-system\r\n uri: lb://ruoyi-system\r\n predicates:\r\n - Path=/system/**\r\n filters:\r\n - StripPrefix=1\r\n # 文件服务\r\n - id: ruoyi-file\r\n uri: lb://ruoyi-file\r\n predicates:\r\n - Path=/file/**\r\n filters:\r\n - StripPrefix=1\r\n\r\n# 不校验白名单\r\nignore:\r\n whites:\r\n - /auth/logout\r\n - /auth/login\r\n - /*/v2/api-docs\r\n - /csrf\r\n','ef4a58daf989827334b3aac1c9d68392','2020-05-14 14:17:55','2020-11-18 17:53:23',NULL,'0:0:0:0:0:0:0:1','','','网关模块','null','null','yaml','null'),
|
(2,'ruoyi-gateway-dev.yml','DEFAULT_GROUP','spring:\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n cloud:\r\n gateway:\r\n discovery:\r\n locator:\r\n lowerCaseServiceId: true\r\n enabled: true\r\n routes:\r\n # 认证中心\r\n - id: ruoyi-auth\r\n uri: lb://ruoyi-auth\r\n predicates:\r\n - Path=/auth/**\r\n filters:\r\n # 验证码处理\r\n - CacheRequestFilter\r\n - ValidateCodeFilter\r\n - StripPrefix=1\r\n # 代码生成\r\n - id: ruoyi-gen\r\n uri: lb://ruoyi-gen\r\n predicates:\r\n - Path=/code/**\r\n filters:\r\n - StripPrefix=1\r\n # 定时任务\r\n - id: ruoyi-job\r\n uri: lb://ruoyi-job\r\n predicates:\r\n - Path=/schedule/**\r\n filters:\r\n - StripPrefix=1\r\n # 系统模块\r\n - id: ruoyi-system\r\n uri: lb://ruoyi-system\r\n predicates:\r\n - Path=/system/**\r\n filters:\r\n - StripPrefix=1\r\n # 文件服务\r\n - id: ruoyi-file\r\n uri: lb://ruoyi-file\r\n predicates:\r\n - Path=/file/**\r\n filters:\r\n - StripPrefix=1\r\n\r\n# 不校验白名单\r\nignore:\r\n whites:\r\n - /auth/logout\r\n - /auth/login\r\n - /*/v2/api-docs\r\n - /csrf\r\n','ef4a58daf989827334b3aac1c9d68392','2020-05-14 14:17:55','2020-11-18 17:53:23',NULL,'0:0:0:0:0:0:0:1','','','网关模块','null','null','yaml','null'),
|
||||||
(3,'ruoyi-auth-dev.yml','DEFAULT_GROUP','spring: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n','868c15010a7a15c027d4c90a48aabb3e','2020-11-20 00:00:00','2020-11-20 00:00:00',NULL,'0:0:0:0:0:0:0:1','','','认证中心','null','null','yaml','null'),
|
(3,'ruoyi-auth-dev.yml','DEFAULT_GROUP','spring: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n','868c15010a7a15c027d4c90a48aabb3e','2020-11-20 00:00:00','2020-11-20 00:00:00',NULL,'0:0:0:0:0:0:0:1','','','认证中心','null','null','yaml','null'),
|
||||||
(4,'ruoyi-monitor-dev.yml','DEFAULT_GROUP','# spring\r\nspring: \r\n security:\r\n user:\r\n name: ruoyi\r\n password: 123456\r\n boot:\r\n admin:\r\n ui:\r\n title: 若依服务状态监控\r\n','d8997d0707a2fd5d9fc4e8409da38129','2020-11-20 00:00:00','2020-12-21 16:28:07',NULL,'0:0:0:0:0:0:0:1','','','监控中心','null','null','yaml','null'),
|
(4,'ruoyi-monitor-dev.yml','DEFAULT_GROUP','# spring\r\nspring: \r\n security:\r\n user:\r\n name: ruoyi\r\n password: 123456\r\n boot:\r\n admin:\r\n ui:\r\n title: 若依服务状态监控\r\n','d8997d0707a2fd5d9fc4e8409da38129','2020-11-20 00:00:00','2020-12-21 16:28:07',NULL,'0:0:0:0:0:0:0:1','','','监控中心','null','null','yaml','null'),
|
||||||
(5,'ruoyi-system-dev.yml','DEFAULT_GROUP','# spring配置\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource:\r\n druid:\r\n stat-view-servlet:\r\n enabled: true\r\n loginUsername: admin\r\n loginPassword: 123456\r\n dynamic:\r\n druid:\r\n initial-size: 5\r\n min-idle: 5\r\n maxActive: 20\r\n maxWait: 60000\r\n timeBetweenEvictionRunsMillis: 60000\r\n minEvictableIdleTimeMillis: 300000\r\n validationQuery: SELECT 1 FROM DUAL\r\n testWhileIdle: true\r\n testOnBorrow: false\r\n testOnReturn: false\r\n poolPreparedStatements: true\r\n maxPoolPreparedStatementPerConnectionSize: 20\r\n filters: stat,wall,slf4j\r\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\r\n datasource:\r\n # 主库数据源\r\n master:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n # 从库数据源\r\n # slave:\r\n # username: \r\n # password: \r\n # url: \r\n # driver-class-name: \r\n # seata: true # 开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\r\n\r\n# seata配置\r\nseata:\r\n # 默认关闭,如需启用spring.datasource.dynami.seata需要同时开启\r\n enabled: false\r\n # Seata 应用编号,默认为 ${spring.application.name}\r\n application-id: ${spring.application.name}\r\n # Seata 事务组编号,用于 TC 集群名\r\n tx-service-group: ${spring.application.name}-group\r\n # 关闭自动代理\r\n enable-auto-data-source-proxy: false\r\n # 服务配置项\r\n service:\r\n # 虚拟组和分组的映射\r\n vgroup-mapping:\r\n ruoyi-system-group: default\r\n config:\r\n type: nacos\r\n nacos:\r\n serverAddr: 127.0.0.1:8848\r\n group: SEATA_GROUP\r\n namespace:\r\n registry:\r\n type: nacos\r\n nacos:\r\n application: seata-server\r\n server-addr: 127.0.0.1:8848\r\n namespace:\r\n\r\n# mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.system\r\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger配置\r\nswagger:\r\n title: 系统模块接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip','ac8913dee679e65bb7d482df5f267d4e','2020-11-20 00:00:00','2021-01-27 10:42:25',NULL,'0:0:0:0:0:0:0:1','','','系统模块','null','null','yaml','null'),
|
(5,'ruoyi-system-dev.yml','DEFAULT_GROUP','# spring配置\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource:\r\n druid:\r\n stat-view-servlet:\r\n enabled: true\r\n loginUsername: admin\r\n loginPassword: 123456\r\n dynamic:\r\n druid:\r\n initial-size: 5\r\n min-idle: 5\r\n maxActive: 20\r\n maxWait: 60000\r\n timeBetweenEvictionRunsMillis: 60000\r\n minEvictableIdleTimeMillis: 300000\r\n validationQuery: SELECT 1 FROM DUAL\r\n testWhileIdle: true\r\n testOnBorrow: false\r\n testOnReturn: false\r\n poolPreparedStatements: true\r\n maxPoolPreparedStatementPerConnectionSize: 20\r\n filters: stat,wall,slf4j\r\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\r\n datasource:\r\n # 主库数据源\r\n master:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n # 从库数据源\r\n # slave:\r\n # username: \r\n # password: \r\n # url: \r\n # driver-class-name: \r\n # seata: true # 开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\r\n\r\n# seata配置\r\nseata:\r\n # 默认关闭,如需启用spring.datasource.dynami.seata需要同时开启\r\n enabled: false\r\n # Seata 应用编号,默认为 ${spring.application.name}\r\n application-id: ${spring.application.name}\r\n # Seata 事务组编号,用于 TC 集群名\r\n tx-service-group: ${spring.application.name}-group\r\n # 关闭自动代理\r\n enable-auto-data-source-proxy: false\r\n # 服务配置项\r\n service:\r\n # 虚拟组和分组的映射\r\n vgroup-mapping:\r\n ruoyi-system-group: default\r\n config:\r\n type: nacos\r\n nacos:\r\n serverAddr: 175.25.50.135:8848\r\n group: SEATA_GROUP\r\n namespace:\r\n registry:\r\n type: nacos\r\n nacos:\r\n application: seata-server\r\n server-addr: 175.25.50.135:8848\r\n namespace:\r\n\r\n# mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.system\r\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger配置\r\nswagger:\r\n title: 系统模块接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip','ac8913dee679e65bb7d482df5f267d4e','2020-11-20 00:00:00','2021-01-27 10:42:25',NULL,'0:0:0:0:0:0:0:1','','','系统模块','null','null','yaml','null'),
|
||||||
(6,'ruoyi-gen-dev.yml','DEFAULT_GROUP','# spring配置\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource: \r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.gen.domain\r\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger配置\r\nswagger:\r\n title: 代码生成接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n\r\n# 代码生成\r\ngen: \r\n # 作者\r\n author: ruoyi\r\n # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool\r\n packageName: com.ruoyi.system\r\n # 自动去除表前缀,默认是false\r\n autoRemovePre: false\r\n # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)\r\n tablePrefix: sys_\r\n','8c79f64a4cca9b821a03dc8b27a2d8eb','2020-11-20 00:00:00','2021-01-26 10:36:45',NULL,'0:0:0:0:0:0:0:1','','','代码生成','null','null','yaml','null'),
|
(6,'ruoyi-gen-dev.yml','DEFAULT_GROUP','# spring配置\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource: \r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.gen.domain\r\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger配置\r\nswagger:\r\n title: 代码生成接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n\r\n# 代码生成\r\ngen: \r\n # 作者\r\n author: ruoyi\r\n # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool\r\n packageName: com.ruoyi.system\r\n # 自动去除表前缀,默认是false\r\n autoRemovePre: false\r\n # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)\r\n tablePrefix: sys_\r\n','8c79f64a4cca9b821a03dc8b27a2d8eb','2020-11-20 00:00:00','2021-01-26 10:36:45',NULL,'0:0:0:0:0:0:0:1','','','代码生成','null','null','yaml','null'),
|
||||||
(7,'ruoyi-job-dev.yml','DEFAULT_GROUP','# spring配置\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.job.domain\r\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger配置\r\nswagger:\r\n title: 定时任务接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n','d6dfade9a2c93c463ae857cd503cb172','2020-11-20 00:00:00','2021-01-26 10:36:04',NULL,'0:0:0:0:0:0:0:1','','','定时任务','null','null','yaml','null'),
|
(7,'ruoyi-job-dev.yml','DEFAULT_GROUP','# spring配置\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.job.domain\r\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger配置\r\nswagger:\r\n title: 定时任务接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n','d6dfade9a2c93c463ae857cd503cb172','2020-11-20 00:00:00','2021-01-26 10:36:04',NULL,'0:0:0:0:0:0:0:1','','','定时任务','null','null','yaml','null'),
|
||||||
(8,'ruoyi-file-dev.yml','DEFAULT_GROUP','# 本地文件上传 \r\nfile:\r\n domain: http://127.0.0.1:9300\r\n path: D:/ruoyi/uploadPath\r\n prefix: /statics\r\n\r\n# FastDFS配置\r\nfdfs:\r\n domain: http://8.129.231.12\r\n soTimeout: 3000\r\n connectTimeout: 2000\r\n trackerList: 8.129.231.12:22122\r\n\r\n# Minio配置\r\nminio:\r\n url: http://8.129.231.12:9000\r\n accessKey: minioadmin\r\n secretKey: minioadmin\r\n bucketName: test','5382b93f3d8059d6068c0501fdd41195','2020-11-20 00:00:00','2020-12-21 21:01:59',NULL,'0:0:0:0:0:0:0:1','','','文件服务','null','null','yaml','null'),
|
(8,'ruoyi-file-dev.yml','DEFAULT_GROUP','# 本地文件上传 \r\nfile:\r\n domain: http://127.0.0.1:9300\r\n path: D:/ruoyi/uploadPath\r\n prefix: /statics\r\n\r\n# FastDFS配置\r\nfdfs:\r\n domain: http://8.129.231.12\r\n soTimeout: 3000\r\n connectTimeout: 2000\r\n trackerList: 8.129.231.12:22122\r\n\r\n# Minio配置\r\nminio:\r\n url: http://8.129.231.12:9000\r\n accessKey: minioadmin\r\n secretKey: minioadmin\r\n bucketName: test','5382b93f3d8059d6068c0501fdd41195','2020-11-20 00:00:00','2020-12-21 21:01:59',NULL,'0:0:0:0:0:0:0:1','','','文件服务','null','null','yaml','null'),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue