若依 1.0

This commit is contained in:
RuoYi
2020-05-20 08:57:11 +08:00
parent 0d44dfa38c
commit eda0dfae86
532 changed files with 47340 additions and 8 deletions

View File

@@ -0,0 +1,30 @@
package com.ruoyi.auth;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
/**
* 认证授权中心
*
* @author ruoyi
*/
@EnableRyFeignClients
@SpringCloudApplication
public class RuoYiAuthApplication
{
public static void main(String[] args)
{
SpringApplication.run(RuoYiAuthApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 认证授权中心启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}

View File

@@ -0,0 +1,129 @@
package com.ruoyi.auth.config;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
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 com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.security.component.RyWebResponseExceptionTranslator;
import com.ruoyi.common.security.domain.LoginUser;
import com.ruoyi.common.security.service.RedisClientDetailsService;
/**
* OAuth2 认证服务配置
*
* @author ruoyi
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter
{
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Autowired
private UserDetailsService userDetailsService;
/**
* 定义授权和令牌端点以及令牌服务
*/
@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 RyWebResponseExceptionTranslator());
}
/**
* 配置令牌端点(Token Endpoint)的安全约束
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
{
oauthServer.allowFormAuthenticationForClients().checkTokenAccess("permitAll()");
}
/**
* 声明 ClientDetails实现
*/
public RedisClientDetailsService clientDetailsService()
{
RedisClientDetailsService clientDetailsService = new RedisClientDetailsService(dataSource);
clientDetailsService.setSelectClientDetailsSql(SecurityConstants.DEFAULT_SELECT_STATEMENT);
clientDetailsService.setFindClientDetailsSql(SecurityConstants.DEFAULT_FIND_STATEMENT);
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) -> {
final Map<String, Object> additionalInfo = new HashMap<>(4);
LoginUser user = (LoginUser) authentication.getUserAuthentication().getPrincipal();
additionalInfo.put(SecurityConstants.DETAILS_LICENSE, SecurityConstants.LICENSE);
additionalInfo.put(SecurityConstants.DETAILS_USER_ID, user.getUserId());
additionalInfo.put(SecurityConstants.DETAILS_USERNAME, user.getUsername());
additionalInfo.put(SecurityConstants.DETAILS_DEPT_ID, user.getDeptId());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
};
}
}

View File

@@ -0,0 +1,68 @@
package com.ruoyi.auth.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
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.builders.WebSecurity;
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;
/**
* Security 安全认证相关配置
* Oauth2依赖于Security 默认情况下WebSecurityConfig执行比ResourceServerConfig优先
*
* @author ruoyi
*/
@Primary
@Order(90)
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
@Autowired
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(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers(
"/actuator/**",
"/token/**").permitAll()
.anyRequest().authenticated()
.and().csrf().disable();
}
/*** 设置不拦截规则 */
@Override
public void configure(WebSecurity web)
{
web.ignoring().antMatchers("/css/**", "/js/**", "/plugins/**", "/favicon.ico");
}
}

View File

@@ -0,0 +1,50 @@
package com.ruoyi.auth.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
/**
* token 控制
*
* @author ruoyi
*/
@RestController
@RequestMapping("/token")
public class TokenController
{
@Autowired
private TokenStore tokenStore;
@DeleteMapping("/logout")
public R<?> logout(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader)
{
if (StringUtils.isEmpty(authHeader))
{
return R.ok();
}
String tokenValue = authHeader.replace(OAuth2AccessToken.BEARER_TYPE, StringUtils.EMPTY).trim();
OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
if (accessToken == null || StringUtils.isEmpty(accessToken.getValue()))
{
return R.ok();
}
// 清空 access token
tokenStore.removeAccessToken(accessToken);
// 清空 refresh token
OAuth2RefreshToken refreshToken = accessToken.getRefreshToken();
tokenStore.removeRefreshToken(refreshToken);
return R.ok();
}
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.auth.controller;
import java.security.Principal;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 身份信息获取
*
* @author ruoyi
*/
@RestController
@RequestMapping("/oauth")
public class UserController
{
@RequestMapping("/user")
public Principal user(Principal user)
{
return user;
}
}

View File

@@ -0,0 +1,33 @@
package com.ruoyi.auth.handler;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.security.handler.AbstractAuthenticationFailureEvenHandler;
/**
* 认证失败处理
*
* @author ruoyi
*/
@Component
public class AuthenticationFailureEvenHandler extends AbstractAuthenticationFailureEvenHandler
{
private final Logger logger = LoggerFactory.getLogger(AuthenticationSuccessEventHandler.class);
@Override
public void handle(AuthenticationException authenticationException, Authentication authentication)
{
HttpServletRequest request = ServletUtils.getRequest();
String url = request.getRequestURI();
String username = (String) authentication.getPrincipal();
logger.info("用户:{} 授权失败url{}", username, url);
}
}

View File

@@ -0,0 +1,40 @@
package com.ruoyi.auth.handler;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.security.domain.LoginUser;
import com.ruoyi.common.security.handler.AbstractAuthenticationSuccessEventHandler;
/**
* 认证成功处理
*
* @author ruoyi
*/
@Component
public class AuthenticationSuccessEventHandler extends AbstractAuthenticationSuccessEventHandler
{
private final Logger logger = LoggerFactory.getLogger(AuthenticationSuccessEventHandler.class);
@Override
public void handle(Authentication authentication)
{
HttpServletRequest request = ServletUtils.getRequest();
String url = request.getRequestURI();
if (authentication.getPrincipal() instanceof LoginUser)
{
LoginUser user = (LoginUser) authentication.getPrincipal();
String username = user.getUsername();
logger.info("用户:{} 授权成功url{}", username, url);
}
}
}

View File

@@ -0,0 +1,10 @@
Spring Boot Version: ${spring-boot.version}
Spring Application Name: ${spring.application.name}
_ _ _
(_) | | | |
_ __ _ _ ___ _ _ _ ______ __ _ _ _ | |_ | |__
| '__|| | | | / _ \ | | | || ||______| / _` || | | || __|| '_ \
| | | |_| || (_) || |_| || | | (_| || |_| || |_ | | | |
|_| \__,_| \___/ \__, ||_| \__,_| \__,_| \__||_| |_|
__/ |
|___/

View File

@@ -0,0 +1,24 @@
# Tomcat
server:
port: 9200
# Spring
spring:
application:
# 应用名称
name: ruoyi-auth
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}