pull/42/head
alikes 5 years ago
parent fff8fb7d86
commit 46eb9a0303

@ -23,6 +23,13 @@
<artifactId>ruoyi-common-core</artifactId>
</dependency>
<!-- spring-security-core -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

@ -1,5 +1,7 @@
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.web.bind.annotation.GetMapping;
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.model.LoginUser;
import java.util.Set;
/**
*
*
@ -23,5 +27,34 @@ public interface RemoteUserService
* @return
*/
@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;
import com.ruoyi.system.api.model.RoleAndPermission;
import com.ruoyi.system.api.model.UserInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@ -8,6 +10,8 @@ import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.model.LoginUser;
import feign.hystrix.FallbackFactory;
import java.util.Set;
/**
*
*
@ -25,10 +29,25 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
return new RemoteUserService()
{
@Override
public R<LoginUser> getUserInfo(String username)
public R<UserInfo> getUserInfo(String username)
{
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;
import java.io.Serializable;
import java.util.Set;
import java.util.*;
import java.util.function.Function;
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
*/
public class LoginUser implements Serializable
@Slf4j
public class LoginUser implements Serializable, UserDetails,CredentialsContainer
{
private static final long serialVersionUID = 1L;
@ -21,7 +34,7 @@ public class LoginUser implements Serializable
/**
* id
*/
private Long userid;
private Long userId;
/**
*
@ -58,6 +71,63 @@ public class LoginUser implements Serializable
*/
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()
{
return token;
@ -68,16 +138,17 @@ public class LoginUser implements Serializable
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()
{
return username;
@ -147,4 +218,221 @@ public class LoginUser implements Serializable
{
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
* Oauth2Security WebSecurityConfigResourceServerConfig
*
* @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;
import javax.servlet.http.HttpServletRequest;
import com.ruoyi.system.api.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -27,16 +29,16 @@ public class TokenController
@Autowired
private SysLoginService sysLoginService;
@PostMapping("login")
public R<?> login(@RequestBody LoginBody form)
{
// 用户登录
LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword());
// 获取登录token
return R.ok(tokenService.createToken(userInfo));
}
// @PostMapping("login")
// public R<?> login(@RequestBody LoginBody form)
// {
// // 用户登录
// UserInfo userInfo = sysLoginService.login(form.getUsername(), form.getPassword());
// // 获取登录token
// return R.ok(tokenService.createToken(userInfo));
// }
@DeleteMapping("logout")
@DeleteMapping("token/logout")
public R<?> logout(HttpServletRequest 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;
import com.ruoyi.system.api.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
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.enums.UserStatus;
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.system.api.RemoteLogService;
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))
@ -54,7 +55,7 @@ public class SysLoginService
throw new BaseException("用户名不在指定范围");
}
// 查询用户信息
R<LoginUser> userResult = remoteUserService.getUserInfo(username);
R<UserInfo> userResult = remoteUserService.getUserInfo(username);
if (R.FAIL == userResult.getCode())
{
@ -66,7 +67,7 @@ public class SysLoginService
remoteLogService.saveLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
throw new BaseException("登录用户:" + username + " 不存在");
}
LoginUser userInfo = userResult.getData();
UserInfo userInfo = userResult.getData();
SysUser user = userResult.getData().getSysUser();
if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{

@ -14,11 +14,12 @@ spring:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
# 配置文件格式
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>
</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>
</project>

@ -36,4 +36,14 @@ public class CacheConstants
*
*/
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_idclient_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;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.text.Convert;
/**
*
*
* @author ruoyi
*/
public class SecurityUtils
{
/**
*
*/
public static String getUsername()
{
String username = ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USERNAME);
return ServletUtils.urlDecode(username);
}
/**
* ID
*/
public static Long getUserId()
{
return Convert.toLong(ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USER_ID));
}
/**
* token
*/
public static String getToken()
{
return getToken(ServletUtils.getRequest());
}
/**
* requesttoken
*/
public static String getToken(HttpServletRequest request)
{
String token = ServletUtils.getRequest().getHeader(CacheConstants.HEADER);
if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX))
{
token = token.replace(CacheConstants.TOKEN_PREFIX, "");
}
return token;
}
/**
*
*
* @param userId ID
* @return
*/
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
}
/**
* 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);
}
}
//package com.ruoyi.common.core.utils;
//
//import javax.servlet.http.HttpServletRequest;
//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
//import com.ruoyi.common.core.constant.CacheConstants;
//import com.ruoyi.common.core.text.Convert;
//
///**
// * 权限获取工具类
// *
// * @author ruoyi
// */
//public class SecurityUtils
//{
// /**
// * 获取用户
// */
// public static String getUsername()
// {
// String username = ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USERNAME);
// return ServletUtils.urlDecode(username);
// }
//
// /**
// * 获取用户ID
// */
// public static Long getUserId()
// {
// return Convert.toLong(ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USER_ID));
// }
//
// /**
// * 获取请求token
// */
// public static String getToken()
// {
// return getToken(ServletUtils.getRequest());
// }
//
// /**
// * 根据request获取请求token
// */
// public static String getToken(HttpServletRequest request)
// {
// String token = ServletUtils.getRequest().getHeader(CacheConstants.HEADER);
// if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX))
// {
// token = token.replace(CacheConstants.TOKEN_PREFIX, "");
// }
// return token;
// }
//
// /**
// * 是否为管理员
// *
// * @param userId 用户ID
// * @return 结果
// */
// public static boolean isAdmin(Long userId)
// {
// return userId != null && 1L == userId;
// }
//
// /**
// * 生成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);
// }
//
//
//
//}

@ -6,6 +6,8 @@ import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.security.utils.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
@ -20,7 +22,6 @@ import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
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.StringUtils;
import com.ruoyi.common.core.utils.ip.IpUtils;

@ -16,6 +16,12 @@
<dependencies>
<!-- Spring Security Oauth2 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<!-- RuoYi Api System -->
<dependency>
<groupId>com.ruoyi</groupId>

@ -6,12 +6,14 @@ import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
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.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.EnableAsync;
import com.ruoyi.common.security.config.ApplicationConfig;
import com.ruoyi.common.security.feign.FeignAutoConfiguration;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ -24,8 +26,7 @@ import com.ruoyi.common.security.feign.FeignAutoConfiguration;
// 开启线程异步执行
@EnableAsync
// 自动加载类
@Import({ ApplicationConfig.class, FeignAutoConfiguration.class })
public @interface EnableCustomConfig
{
@Import({ ApplicationConfig.class, FeignConfig.class , SecurityImportBeanDefinitionRegistrar.class})
public @interface EnableCustomConfig {
}

@ -8,6 +8,7 @@ import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.PatternMatchUtils;
@ -111,11 +112,11 @@ public class PreAuthorizeAspect
public boolean hasPermi(String permission)
{
LoginUser userInfo = tokenService.getLoginUser();
if (StringUtils.isEmpty(userInfo) || CollectionUtils.isEmpty(userInfo.getPermissions()))
if (StringUtils.isEmpty(userInfo) || CollectionUtils.isEmpty(userInfo.getAuthorities()))
{
return false;
}
return hasPermissions(userInfo.getPermissions(), permission);
return hasPermissions(userInfo.getAuthorities(), permission);
}
/**
@ -142,7 +143,7 @@ public class PreAuthorizeAspect
{
return false;
}
Collection<String> authorities = userInfo.getPermissions();
Collection<GrantedAuthority> authorities = userInfo.getAuthorities();
for (String permission : permissions)
{
if (permission != null && hasPermissions(authorities, permission))
@ -217,9 +218,8 @@ public class PreAuthorizeAspect
* @param permission
* @return
*/
private boolean hasPermissions(Collection<String> authorities, String permission)
private boolean hasPermissions(Collection<GrantedAuthority> authorities, String permission)
{
return authorities.stream().filter(StringUtils::hasText)
.anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(permission, x));
return authorities.stream().filter(grantedAuthority-> {return StringUtils.hasText(grantedAuthority.getAuthority());}).anyMatch(grantedAuthority -> ALL_PERMISSION.contains(grantedAuthority.getAuthority()) || PatternMatchUtils.simpleMatch(permission, grantedAuthority.getAuthority()));
}
}

@ -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;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import feign.RequestInterceptor;
/**
* Feign
*
* @author ruoyi
**/
@Configuration
public class FeignAutoConfiguration
{
@Bean
public RequestInterceptor requestInterceptor()
{
return new FeignRequestInterceptor();
}
}
//package com.ruoyi.common.security.feign;
//
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import feign.RequestInterceptor;
//
///**
// * Feign 配置注册
// *
// * @author ruoyi
// **/
//@Configuration
//public class FeignAutoConfiguration
//{
// @Bean
// public RequestInterceptor requestInterceptor()
// {
// 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;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils;
import feign.RequestInterceptor;
import feign.RequestTemplate;
/**
* feign
*
* @author ruoyi
*/
@Component
public class FeignRequestInterceptor implements RequestInterceptor
{
@Override
public void apply(RequestTemplate requestTemplate)
{
HttpServletRequest httpServletRequest = ServletUtils.getRequest();
if (StringUtils.isNotNull(httpServletRequest))
{
Map<String, String> headers = ServletUtils.getHeaders(httpServletRequest);
// 传递用户信息请求头,防止丢失
String userId = headers.get(CacheConstants.DETAILS_USER_ID);
if (StringUtils.isNotEmpty(userId))
{
requestTemplate.header(CacheConstants.DETAILS_USER_ID, userId);
}
String userName = headers.get(CacheConstants.DETAILS_USERNAME);
if (StringUtils.isNotEmpty(userName))
{
requestTemplate.header(CacheConstants.DETAILS_USERNAME, userName);
}
String authentication = headers.get(CacheConstants.AUTHORIZATION_HEADER);
if (StringUtils.isNotEmpty(authentication))
{
requestTemplate.header(CacheConstants.AUTHORIZATION_HEADER, authentication);
}
}
}
}
//package com.ruoyi.common.security.feign;
//
//import java.util.Map;
//import javax.servlet.http.HttpServletRequest;
//import org.springframework.stereotype.Component;
//import com.ruoyi.common.core.constant.CacheConstants;
//import com.ruoyi.common.core.utils.ServletUtils;
//import com.ruoyi.common.core.utils.StringUtils;
//import feign.RequestInterceptor;
//import feign.RequestTemplate;
//
///**
// * feign 请求拦截器
// *
// * @author ruoyi
// */
//@Component
//public class FeignRequestInterceptor implements RequestInterceptor
//{
// @Override
// public void apply(RequestTemplate requestTemplate)
// {
// HttpServletRequest httpServletRequest = ServletUtils.getRequest();
// if (StringUtils.isNotNull(httpServletRequest))
// {
// Map<String, String> headers = ServletUtils.getHeaders(httpServletRequest);
// // 传递用户信息请求头,防止丢失
// String userId = headers.get(CacheConstants.DETAILS_USER_ID);
// if (StringUtils.isNotEmpty(userId))
// {
// requestTemplate.header(CacheConstants.DETAILS_USER_ID, userId);
// }
// String userName = headers.get(CacheConstants.DETAILS_USERNAME);
// if (StringUtils.isNotEmpty(userName))
// {
// requestTemplate.header(CacheConstants.DETAILS_USERNAME, userName);
// }
// String authentication = headers.get(CacheConstants.AUTHORIZATION_HEADER);
// if (StringUtils.isNotEmpty(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.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import com.ruoyi.common.security.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.Constants;
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.StringUtils;
import com.ruoyi.common.core.utils.ip.IpUtils;
@ -41,7 +42,7 @@ public class TokenService
// 生成token
String token = IdUtils.fastUUID();
loginUser.setToken(token);
loginUser.setUserid(loginUser.getSysUser().getUserId());
loginUser.setUserId(loginUser.getSysUser().getUserId());
loginUser.setUsername(loginUser.getSysUser().getUserName());
loginUser.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
refreshToken(loginUser);
@ -71,15 +72,17 @@ public class TokenService
*/
public LoginUser getLoginUser(HttpServletRequest request)
{
// 获取请求携带的令牌
String token = SecurityUtils.getToken(request);
if (StringUtils.isNotEmpty(token))
{
String userKey = getTokenKey(token);
LoginUser user = redisService.getCacheObject(userKey);
return user;
}
return null;
// // 获取请求携带的令牌
// String token = SecurityUtils.getToken(request);
// if (StringUtils.isNotEmpty(token))
// {
// String userKey = getTokenKey(token);
// LoginUser user = redisService.getCacheObject(userKey);
// LoginUser user = SecurityUtils.getLoginUser();
//
// }
// 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.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
@ -96,9 +92,20 @@ public class SwaggerAutoConfiguration
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("^(?!auth).*$"))
.build());
securityContexts.add(SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex(swaggerProperties().getAuthorization().getAuthRegex()))
.build());
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;
}
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)
{
return new ApiInfoBuilder()

@ -1,125 +1,125 @@
package com.ruoyi.gateway.filter;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.gateway.config.properties.IgnoreWhiteProperties;
import reactor.core.publisher.Mono;
/**
*
*
* @author ruoyi
*/
@Component
public class AuthFilter implements GlobalFilter, Ordered
{
private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
private final static long EXPIRE_TIME = Constants.TOKEN_EXPIRE * 60;
// 排除过滤的 uri 地址nacos自行添加
@Autowired
private IgnoreWhiteProperties ignoreWhite;
@Resource(name = "stringRedisTemplate")
private ValueOperations<String, String> sops;
@Autowired
private RedisService redisService;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
{
String url = exchange.getRequest().getURI().getPath();
// 跳过不需要验证的路径
if (StringUtils.matches(url, ignoreWhite.getWhites()))
{
return chain.filter(exchange);
}
String token = getToken(exchange.getRequest());
if (StringUtils.isBlank(token))
{
return setUnauthorizedResponse(exchange, "令牌不能为空");
}
String userStr = sops.get(getTokenKey(token));
if (StringUtils.isNull(userStr))
{
return setUnauthorizedResponse(exchange, "登录状态已过期");
}
JSONObject obj = JSONObject.parseObject(userStr);
String userid = obj.getString("userid");
String username = obj.getString("username");
if (StringUtils.isBlank(userid) || StringUtils.isBlank(username))
{
return setUnauthorizedResponse(exchange, "令牌验证失败");
}
// 设置过期时间
redisService.expire(getTokenKey(token), EXPIRE_TIME);
// 设置用户信息到请求
ServerHttpRequest mutableReq = exchange.getRequest().mutate().header(CacheConstants.DETAILS_USER_ID, userid)
.header(CacheConstants.DETAILS_USERNAME, ServletUtils.urlEncode(username)).build();
ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
return chain.filter(mutableExchange);
}
private Mono<Void> setUnauthorizedResponse(ServerWebExchange exchange, String msg)
{
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
response.setStatusCode(HttpStatus.OK);
log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
return response.writeWith(Mono.fromSupplier(() -> {
DataBufferFactory bufferFactory = response.bufferFactory();
return bufferFactory.wrap(JSON.toJSONBytes(R.fail(msg)));
}));
}
private String getTokenKey(String token)
{
return CacheConstants.LOGIN_TOKEN_KEY + token;
}
/**
* token
*/
private String getToken(ServerHttpRequest request)
{
String token = request.getHeaders().getFirst(CacheConstants.HEADER);
if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX))
{
token = token.replace(CacheConstants.TOKEN_PREFIX, "");
}
return token;
}
@Override
public int getOrder()
{
return -200;
}
}
//package com.ruoyi.gateway.filter;
//
//import javax.annotation.Resource;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
//import org.springframework.cloud.gateway.filter.GlobalFilter;
//import org.springframework.core.Ordered;
//import org.springframework.core.io.buffer.DataBufferFactory;
//import org.springframework.data.redis.core.ValueOperations;
//import org.springframework.http.HttpStatus;
//import org.springframework.http.MediaType;
//import org.springframework.http.server.reactive.ServerHttpRequest;
//import org.springframework.http.server.reactive.ServerHttpResponse;
//import org.springframework.stereotype.Component;
//import org.springframework.web.server.ServerWebExchange;
//import com.alibaba.fastjson.JSON;
//import com.alibaba.fastjson.JSONObject;
//import com.ruoyi.common.core.constant.CacheConstants;
//import com.ruoyi.common.core.constant.Constants;
//import com.ruoyi.common.core.domain.R;
//import com.ruoyi.common.core.utils.ServletUtils;
//import com.ruoyi.common.core.utils.StringUtils;
//import com.ruoyi.common.redis.service.RedisService;
//import com.ruoyi.gateway.config.properties.IgnoreWhiteProperties;
//import reactor.core.publisher.Mono;
//
///**
// * 网关鉴权
// *
// * @author ruoyi
// */
//@Component
//public class AuthFilter implements GlobalFilter, Ordered
//{
// private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
//
// private final static long EXPIRE_TIME = Constants.TOKEN_EXPIRE * 60;
//
// // 排除过滤的 uri 地址nacos自行添加
// @Autowired
// private IgnoreWhiteProperties ignoreWhite;
//
// @Resource(name = "stringRedisTemplate")
// private ValueOperations<String, String> sops;
//
// @Autowired
// private RedisService redisService;
//
// @Override
// public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
// {
// String url = exchange.getRequest().getURI().getPath();
// // 跳过不需要验证的路径
// if (StringUtils.matches(url, ignoreWhite.getWhites()))
// {
// return chain.filter(exchange);
// }
// String token = getToken(exchange.getRequest());
// if (StringUtils.isBlank(token))
// {
// return setUnauthorizedResponse(exchange, "令牌不能为空");
// }
// String userStr = sops.get(getTokenKey(token));
// if (StringUtils.isNull(userStr))
// {
// return setUnauthorizedResponse(exchange, "登录状态已过期");
// }
// JSONObject obj = JSONObject.parseObject(userStr);
// String userid = obj.getString("userid");
// String username = obj.getString("username");
// if (StringUtils.isBlank(userid) || StringUtils.isBlank(username))
// {
// return setUnauthorizedResponse(exchange, "令牌验证失败");
// }
//
// // 设置过期时间
// redisService.expire(getTokenKey(token), EXPIRE_TIME);
// // 设置用户信息到请求
// ServerHttpRequest mutableReq = exchange.getRequest().mutate().header(CacheConstants.DETAILS_USER_ID, userid)
// .header(CacheConstants.DETAILS_USERNAME, ServletUtils.urlEncode(username)).build();
// ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
//
// return chain.filter(mutableExchange);
// }
//
// private Mono<Void> setUnauthorizedResponse(ServerWebExchange exchange, String msg)
// {
// ServerHttpResponse response = exchange.getResponse();
// response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
// response.setStatusCode(HttpStatus.OK);
//
// log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
//
// return response.writeWith(Mono.fromSupplier(() -> {
// DataBufferFactory bufferFactory = response.bufferFactory();
// return bufferFactory.wrap(JSON.toJSONBytes(R.fail(msg)));
// }));
// }
//
// private String getTokenKey(String token)
// {
// return CacheConstants.LOGIN_TOKEN_KEY + token;
// }
//
// /**
// * 获取请求token
// */
// private String getToken(ServerHttpRequest request)
// {
// String token = request.getHeaders().getFirst(CacheConstants.HEADER);
// if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX))
// {
// token = token.replace(CacheConstants.TOKEN_PREFIX, "");
// }
// return token;
// }
//
// @Override
// public int getOrder()
// {
// return -200;
// }
//}

@ -16,14 +16,15 @@ spring:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
# 配置文件格式
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:
# 取消控制台懒加载
eager: true
@ -34,7 +35,7 @@ spring:
datasource:
ds1:
nacos:
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
dataId: sentinel-ruoyi-gateway
groupId: DEFAULT_GROUP
data-type: json

@ -14,11 +14,12 @@ spring:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
# 配置文件格式
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.exception.CustomException;
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.file.FileUtils;
import com.ruoyi.gen.domain.GenTable;

@ -14,11 +14,12 @@ spring:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
# 配置文件格式
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.RestController;
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.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;

@ -14,11 +14,12 @@ spring:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
# 配置文件格式
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>
<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>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
@ -145,6 +172,10 @@
<version>1.16.1</version>
<scope>test</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.ruoyi</groupId>-->
<!-- <artifactId>ruoyi-common-security</artifactId>-->
<!-- </dependency>-->
</dependencies>
<build>

@ -17,15 +17,20 @@ package com.alibaba.csp.sentinel.dashboard;
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.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
/**
* Sentinel dashboard application.
*
* @author Carpenter Lee
*/
@SpringBootApplication
//@EnableCustomConfig
//@EnableRyFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class RuoYiSentinelDashboardApplication {
public static void main(String[] args) {

@ -47,8 +47,8 @@ public class WebConfig implements WebMvcConfigurer {
private final Logger logger = LoggerFactory.getLogger(WebConfig.class);
@Autowired
private LoginAuthenticationFilter loginAuthenticationFilter;
// @Autowired
// private LoginAuthenticationFilter loginAuthenticationFilter;
@Autowired
private AuthorizationInterceptor authorizationInterceptor;
@ -104,13 +104,13 @@ public class WebConfig implements WebMvcConfigurer {
});
}
@Bean
public FilterRegistrationBean authenticationFilterRegistration() {
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
registration.setFilter(loginAuthenticationFilter);
registration.addUrlPatterns("/*");
registration.setName("authenticationFilter");
registration.setOrder(0);
return registration;
}
// @Bean
// public FilterRegistrationBean authenticationFilterRegistration() {
// FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
// registration.setFilter(loginAuthenticationFilter);
// registration.addUrlPatterns("/*");
// registration.setName("authenticationFilter");
// registration.setOrder(0);
// 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 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.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.util.StringUtil;
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.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import org.slf4j.Logger;
@ -51,7 +50,7 @@ import org.springframework.web.bind.annotation.RestController;
*/
@RestController
@RequestMapping(value = "/v2/flow")
public class FlowControllerV2 {
public class FlowControllerV2 extends BaseController {
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;
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.datasource.Converter;
import com.alibaba.fastjson.JSON;
@ -36,7 +37,7 @@ import java.util.Properties;
@Configuration
public class NacosConfig {
@Value("${spring.nacos.server-addr}")
@Value("${spring.cloud.nacos.config.server-addr}")
private String serverAddr;
@Bean
@ -49,6 +50,16 @@ public class NacosConfig {
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
public ConfigService nacosConfigService() throws Exception {
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>&nbsp;&nbsp;新增降级规则</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 -->

@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
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.web.controller.BaseController;
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.RestController;
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.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;

@ -4,6 +4,8 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.security.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
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.RequestMapping;
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.poi.ExcelUtil;
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.RestController;
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.web.controller.BaseController;
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 com.ruoyi.common.core.constant.Constants;
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.web.controller.BaseController;
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.RequestMapping;
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.domain.AjaxResult;
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.RestController;
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.web.controller.BaseController;
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.multipart.MultipartFile;
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.StringUtils;
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.RestController;
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.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;

@ -5,7 +5,11 @@ import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
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.security.core.GrantedAuthority;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
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 com.ruoyi.common.core.constant.UserConstants;
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.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
@ -101,7 +104,7 @@ public class SysUserController extends BaseController
*
*/
@GetMapping("/info/{username}")
public R<LoginUser> info(@PathVariable("username") String username)
public R<UserInfo> info(@PathVariable("username") String username)
{
SysUser sysUser = userService.selectUserByUserName(username);
if (StringUtils.isNull(sysUser))
@ -112,7 +115,7 @@ public class SysUserController extends BaseController
Set<String> roles = permissionService.getRolePermission(sysUser.getUserId());
// 权限集合
Set<String> permissions = permissionService.getMenuPermission(sysUser.getUserId());
LoginUser sysUserVo = new LoginUser();
UserInfo sysUserVo = new UserInfo();
sysUserVo.setSysUser(sysUser);
sysUserVo.setRoles(roles);
sysUserVo.setPermissions(permissions);

@ -11,7 +11,7 @@ import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
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.system.api.domain.SysRole;
import com.ruoyi.system.api.domain.SysUser;

@ -9,7 +9,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.core.constant.UserConstants;
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.datascope.annotation.DataScope;
import com.ruoyi.system.api.domain.SysRole;

@ -14,11 +14,12 @@ spring:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
# 配置文件格式
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 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) {
const grant_type = 'password'
return request({
url: '/auth/login',
url: '/auth/oauth/token',
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({
url: '/auth/refresh',
method: 'post'
url: '/auth/oauth/token',
method: 'post',
params: { client_id, client_secret, grant_type, scope, refresh_token }
})
}
@ -32,7 +76,7 @@ export function getInfo() {
// 退出方法
export function logout() {
return request({
url: '/auth/logout',
url: '/auth/token/logout',
method: 'delete'
})
}

@ -1,9 +1,10 @@
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 = {
state: {
token: getToken(),
refresh_token: getRefreshToken(),
name: '',
avatar: '',
roles: [],
@ -17,6 +18,9 @@ const user = {
SET_EXPIRES_IN: (state, time) => {
state.expires_in = time
},
SET_REFRESH_TOKEN: (state, token) => {
state.refresh_token = token
},
SET_NAME: (state, name) => {
state.name = name
},
@ -32,6 +36,25 @@ const user = {
},
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) {
const username = userInfo.username.trim()
@ -40,11 +63,12 @@ const user = {
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)
setToken(res.access_token)
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()
}).catch(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
RefreshToken({commit, state}) {
return new Promise((resolve, reject) => {
refreshToken(state.token).then(res => {
setExpiresIn(res.data)
commit('SET_EXPIRES_IN', res.data)
refreshToken(state.refresh_token).then(res => {
setToken(res.access_token)
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()
}).catch(error => {
reject(error)

@ -1,7 +1,7 @@
import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token'
const RefreshTokenKey = 'Admin-Refresh-Token'
const ExpiresInKey = 'Admin-Expires-In'
export function getToken() {
@ -16,6 +16,18 @@ export function removeToken() {
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() {
return Cookies.get(ExpiresInKey) || -1
}

@ -127,8 +127,9 @@ export default {
Cookies.remove('rememberMe');
}
this.$store.dispatch("Login", this.loginForm).then(() => {
this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
}).catch(() => {
this.$router.push({ path: this.redirect || "/" }).catch((e)=>{console.log(e);});
}).catch((e) => {
console.log(e);
this.loading = false;
this.getCode();
});

@ -14,11 +14,12 @@ spring:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
server-addr: 175.25.50.135:8848
# 配置文件格式
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'),
(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'),
(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'),
(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'),

Loading…
Cancel
Save