update 2021年11月4日18:33:20

master
zhangmeng 2021-11-05 18:36:40 +08:00
parent c5125175d9
commit f4499162c0
12 changed files with 197 additions and 108 deletions

View File

@ -1,30 +1,54 @@
package com.zhangmeng.admin.manager.controller; package com.zhangmeng.admin.manager.controller;
import com.zhangmeng.admin.manager.service.PermissionService;
import com.zhangmeng.admin.manager.utils.UserUtil;
import com.zhangmeng.model.base.baseController.BaseController; import com.zhangmeng.model.base.baseController.BaseController;
import com.zhangmeng.model.dto.Menu;
import com.zhangmeng.model.entity.Permission;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import java.util.List;
import java.util.UUID;
/** /**
* *
* *
* @author zhangmeng * @author zhangmeng
* @date 202111414:18:48
* @version 1.0 * @version 1.0
* @date 202111414:18:48
*/ */
@Controller @Controller
public class RequestController extends BaseController { public class RequestController extends BaseController {
@Autowired
private UserUtil userUtil;
@Autowired
private PermissionService permissionService;
//登录 //登录
@RequestMapping("/login") @RequestMapping("/login")
public ModelAndView login (){ public ModelAndView login() {
return this.jumpPage("admin/login"); return this.jumpPage("admin/login");
} }
//首页 //首页
@RequestMapping("/admin/index") @RequestMapping("/admin/index")
public ModelAndView index (){ public ModelAndView index(Model model) {
String uuid = UUID.randomUUID().toString();
model.addAttribute("uuid", uuid);
model.addAttribute("loginUser", this.userUtil.currentUser());
return this.jumpPage("admin/index"); return this.jumpPage("admin/index");
} }
@GetMapping("/user/menuList")
public List<Menu> permissionList() {
List<Permission> permissions = this.permissionService.findByUserId(this.userUtil.currentUser().getId());
return this.permissionService.toUserMenus(permissions, 0L);
}
} }

View File

@ -0,0 +1,27 @@
package com.zhangmeng.admin.manager.utils;
import com.zhangmeng.model.bean.TokenTools;
import com.zhangmeng.model.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.zhangmeng.admin.manager.service.UserService;
import java.util.Map;
@Component
public class UserUtil {
@Autowired
private TokenTools tokenTools;
@Autowired
private UserService userService;
public User currentUser() {
Map<String, Object> userInfo = this.tokenTools.getUserInfo();
return this.userService.loadUserByUsername(userInfo.get("username").toString());
}
public Map<String,Object> claims(){
return this.tokenTools.getUserInfo();
}
}

View File

@ -3,6 +3,7 @@ function postToPage(url, token) {
f.style.display = 'none'; f.style.display = 'none';
f.action = url; f.action = url;
f.method = 'post'; f.method = 'post';
f.enctype ='application/x-www-form-urlencoded';
f.innerHTML = '<input type="hidden" name="Authorization" value="' + token + '"/>'; f.innerHTML = '<input type="hidden" name="Authorization" value="' + token + '"/>';
document.body.appendChild(f); document.body.appendChild(f);
f.submit(); f.submit();

View File

@ -59,7 +59,7 @@ layui.define(['table', 'jquery', 'element'], function(exports) {
menuTitle: dom.attr("menu-title"), menuTitle: dom.attr("menu-title"),
menuPath: dom.attr("menu-title"), menuPath: dom.attr("menu-title"),
menuIcon: dom.attr("menu-icon"), menuIcon: dom.attr("menu-icon"),
menuUrl: dom.attr("menu-url") + "?token=" + localStorage.getItem("token"), menuUrl: dom.attr("menu-url") + "?Authorization=" + localStorage.getItem("Authorization"),
openType: dom.attr("open-type") openType: dom.attr("open-type")
}; };
var doms = hash(dom); var doms = hash(dom);
@ -164,7 +164,8 @@ layui.define(['table', 'jquery', 'element'], function(exports) {
function getData(url) { function getData(url) {
var defer = $.Deferred(); var defer = $.Deferred();
$.get(url + "?token="+localStorage.getItem("token")+"&fresh=" + Math.random(), function(result) { $.setRequestHeader('Authorization',localStorage.getItem("Authorization"));
$.get(url + "?access_token="+localStorage.getItem("Authorization")+"&fresh=" + Math.random(), function(result) {
defer.resolve(result) defer.resolve(result)
}); });
return defer.promise(); return defer.promise();
@ -172,9 +173,9 @@ layui.define(['table', 'jquery', 'element'], function(exports) {
function postData(url) { function postData(url) {
var defer = $.Deferred(); var defer = $.Deferred();
$.post(url + "?token="+localStorage.getItem("token")+"&fresh=" + Math.random(), function(result) { $.post(url + "?access_token="+localStorage.getItem("Authorization")+"&fresh=" + Math.random(), function(result) {
defer.resolve(result) defer.resolve(result)
}); },);
return defer.promise(); return defer.promise();
} }

View File

@ -470,7 +470,7 @@ layui.define(['jquery', 'element'], function(exports) {
TitleItem += '<i class="layui-icon layui-unselect layui-tab-close">ဆ</i></li>'; TitleItem += '<i class="layui-icon layui-unselect layui-tab-close">ဆ</i></li>';
title += TitleItem; title += TitleItem;
var token = localStorage.getItem("token"); var token = localStorage.getItem("Authorization");
if (option.index == index) { if (option.index == index) {
// 处 理 显 示 内 容 // 处 理 显 示 内 容

View File

@ -4,11 +4,11 @@ logo:
## 网站名称 ## 网站名称
title: "MY Style" title: "MY Style"
## 网站图标 ## 网站图标
image: "/system/admin/images/logo.png" image: "/mystyle-cloud-admin-manager/system/admin/images/logo.png"
## 菜单配置 ## 菜单配置
menu: menu:
## 菜单数据来源 ## 菜单数据来源
data: "/user/menuList" data: "/mystyle-cloud-admin-manager/user/menuList"
## 菜单接口的请求方式 GET / POST ## 菜单接口的请求方式 GET / POST
method: "GET" method: "GET"
## 是否同时只打开一个菜单目录 ## 是否同时只打开一个菜单目录

View File

@ -150,6 +150,7 @@
url: '/article/save', url: '/article/save',
data: obj, data: obj,
type: 'post', type: 'post',
data:{}
success: function (result) { success: function (result) {
if (result.flag) { if (result.flag) {
layer.msg(result.message, {icon: 1, time: 1000}, function () { layer.msg(result.message, {icon: 1, time: 1000}, function () {

View File

@ -10,6 +10,10 @@
<link rel="stylesheet" href="${springMacroRequestContext.contextPath}/mystyle-cloud-admin-manager/system/admin/css/load.css" /> <link rel="stylesheet" href="${springMacroRequestContext.contextPath}/mystyle-cloud-admin-manager/system/admin/css/load.css" />
<!-- 布 局 样 式 --> <!-- 布 局 样 式 -->
<link rel="stylesheet" href="${springMacroRequestContext.contextPath}/mystyle-cloud-admin-manager/system/admin/css/admin.css" /> <link rel="stylesheet" href="${springMacroRequestContext.contextPath}/mystyle-cloud-admin-manager/system/admin/css/admin.css" />
<!-- 依 赖 脚 本 -->
<script src="${springMacroRequestContext.contextPath}/mystyle-cloud-admin-manager/system/component/layui/layui.js"></script>
<script src="${springMacroRequestContext.contextPath}/mystyle-cloud-admin-manager/system/component/pear/pear.js"></script>
</head> </head>
<!-- 结 构 代 码 --> <!-- 结 构 代 码 -->
<body class="layui-layout-body pear-admin"> <body class="layui-layout-body pear-admin">
@ -32,7 +36,7 @@
<!-- 头 像 --> <!-- 头 像 -->
<a href="javascript:;"> <a href="javascript:;">
<#if loginUser.avatar??> <#if loginUser.avatar??>
<img src="${springMacroRequestContext.contextPath}/system/admin/images/avatar.jpg" class="layui-nav-img"> <img src="${springMacroRequestContext.contextPath}/mystyle-cloud-admin-manager/system/admin/images/avatar.jpg" class="layui-nav-img">
<#else > <#else >
<img src="${loginUser.avatar!}" class="layui-nav-img"> <img src="${loginUser.avatar!}" class="layui-nav-img">
</#if> </#if>
@ -78,9 +82,7 @@
<div class="pear-collasped-pe collaspe"> <div class="pear-collasped-pe collaspe">
<a href="#" class="layui-icon layui-icon-shrink-right"></a> <a href="#" class="layui-icon layui-icon-shrink-right"></a>
</div> </div>
<!-- 依 赖 脚 本 -->
<script src="${springMacroRequestContext.contextPath}/mystyle-cloud-admin-manager/system/component/layui/layui.js"></script>
<script src="${springMacroRequestContext.contextPath}/mystyle-cloud-admin-manager/system/component/pear/pear.js"></script>
<!-- 框 架 初 始 化 --> <!-- 框 架 初 始 化 -->
<script> <script>
layui.use(['admin','jquery','convert','popup'], function() { layui.use(['admin','jquery','convert','popup'], function() {
@ -96,7 +98,7 @@
// 你可以通过 admin.setConfigPath 方法修改配置文件位置 // 你可以通过 admin.setConfigPath 方法修改配置文件位置
// 你可以通过 admin.setConfigType 方法修改配置文件类型 // 你可以通过 admin.setConfigType 方法修改配置文件类型
admin.setConfigType("yml"); admin.setConfigType("yml");
admin.setConfigPath("${springMacroRequestContext.contextPath}/system/config/pear.config.yml"); admin.setConfigPath("${springMacroRequestContext.contextPath}/mystyle-cloud-admin-manager/system/config/pear.config.yml");
admin.render(); admin.render();
// 登出逻辑 // 登出逻辑

View File

@ -10,18 +10,6 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>mystyle-cloud-gateway</artifactId> <artifactId>mystyle-cloud-gateway</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies> <dependencies>
<dependency> <dependency>
@ -64,12 +52,19 @@
<artifactId>spring-cloud-sleuth-zipkin</artifactId> <artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.4.4</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -1,50 +0,0 @@
package com.zhangmeng.gateway.feign;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.stream.Collectors;
/**
*
*/
@Configuration
public class FeignOauth2RequestInterceptor implements RequestInterceptor {
@Bean
@ConditionalOnMissingBean
public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
}
@Override
public void apply(RequestTemplate requestTemplate) {
// 获取的全部请求信息
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null){
HttpServletRequest request = attributes.getRequest();
// 获取所有的请求头信息
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null){
while (headerNames.hasMoreElements()){
// 获取请求头的key
String element = headerNames.nextElement();
// 获取请求头的value
String value = request.getHeader(element);
// 将请求头信息放入到请求头
requestTemplate.header(element,value);
}
}
}
}
}

View File

@ -1,35 +1,34 @@
package com.zhangmeng.gateway.filter; package com.zhangmeng.gateway.filter;
import com.zhangmeng.gateway.feign.TokenFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpCookie; import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.codec.multipart.Part;
import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
import java.util.Map; import java.util.Map;
import java.util.TreeMap;
/** /**
* :( ) * :( )
* */
* */
@Component @Component
public class AuthorizeFilter implements GlobalFilter, Ordered { public class AuthorizeFilter implements GlobalFilter, Ordered {
private static final String AUTHORIZE_TOKEN = "Authorization"; private static final String AUTHORIZE_TOKEN = "Authorization";
@Autowired
private TokenFeign tokenFeign;
@Override @Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
@ -39,20 +38,20 @@ public class AuthorizeFilter implements GlobalFilter, Ordered {
ServerHttpResponse response = exchange.getResponse(); ServerHttpResponse response = exchange.getResponse();
//3.判断 是否为登录的URL 如果是 放行 //3.判断 是否为登录的URL 如果是 放行
if(request.getURI().getPath().startsWith("/mystyle-cloud-oauth/user/login")){ if (request.getURI().getPath().startsWith("/mystyle-cloud-oauth/user/login")) {
return chain.filter(exchange); return chain.filter(exchange);
} }
if (request.getURI().getPath().startsWith("/mystyle-cloud-admin-manager/login")){ if (request.getURI().getPath().startsWith("/mystyle-cloud-admin-manager/login")) {
return chain.filter(exchange); return chain.filter(exchange);
} }
if (request.getURI().getPath().startsWith("/mystyle-cloud-admin-manager/system")){ if (request.getURI().getPath().startsWith("/mystyle-cloud-admin-manager/system")) {
return chain.filter(exchange); return chain.filter(exchange);
} }
//mystyle-cloud-admin-manager/verificationCode/generate 验证码 //mystyle-cloud-admin-manager/verificationCode/generate 验证码
if (request.getURI().getPath().startsWith("/mystyle-cloud-admin-manager/verificationCode/generate")){ if (request.getURI().getPath().startsWith("/mystyle-cloud-admin-manager/verificationCode/generate")) {
return chain.filter(exchange); return chain.filter(exchange);
} }
@ -60,39 +59,60 @@ public class AuthorizeFilter implements GlobalFilter, Ordered {
//4.1 从头header中获取令牌数据 //4.1 从头header中获取令牌数据
String token = request.getHeaders().getFirst(AUTHORIZE_TOKEN); String token = request.getHeaders().getFirst(AUTHORIZE_TOKEN);
if(StringUtils.isEmpty(token)){ if (StringUtils.isEmpty(token)) {
//4.3 从请求参数中获取令牌数据
token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN);
}
if (StringUtils.isEmpty(token)) {
//4.2 从cookie中中获取令牌数据 //4.2 从cookie中中获取令牌数据
HttpCookie first = request.getCookies().getFirst(AUTHORIZE_TOKEN); HttpCookie first = request.getCookies().getFirst(AUTHORIZE_TOKEN);
if(first!=null){ if (first != null) {
token=first.getValue();//就是令牌的数据 token = first.getValue();//就是令牌的数据
} }
} }
if(StringUtils.isEmpty(token)){ if (StringUtils.isEmpty(token)) {
//4.3 从请求参数中获取令牌数据
token= request.getQueryParams().getFirst(AUTHORIZE_TOKEN);
}
if(StringUtils.isEmpty(token)){
//4.4. 如果没有数据 结束. //4.4. 如果没有数据 结束.
response.setStatusCode(HttpStatus.UNAUTHORIZED); response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete(); return response.setComplete();
} }
ServerHttpRequest new_request = request.mutate().header(AUTHORIZE_TOKEN, "bearer " + token).build();
//5 解析令牌数据 ( 判断解析是否正确,正确 就放行 ,否则 结束) //5 解析令牌数据 ( 判断解析是否正确,正确 就放行 ,否则 结束)
ServerWebExchange newExchange = exchange.mutate().request(new_request).response(response).build();
try { try {
//this.tokenFeign.parseToken(token);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
//解析失败 //解析失败
response.setStatusCode(HttpStatus.UNAUTHORIZED); response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete(); return response.setComplete();
} }
return chain.filter(exchange); return chain.filter(newExchange);
} }
@Override @Override
public int getOrder() { public int getOrder() {
return 0; return 0;
} }
/**
*
* @param serverHttpRequest
* @return
*/
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest){
//获取请求体
Flux<DataBuffer> body = serverHttpRequest.getBody();
StringBuilder sb = new StringBuilder();
body.subscribe(buffer -> {
byte[] bytes = new byte[buffer.readableByteCount()];
buffer.read(bytes);
DataBufferUtils.release(buffer);
String bodyString = new String(bytes, StandardCharsets.UTF_8);
sb.append(bodyString);
});
return sb.toString();
}
} }

View File

@ -0,0 +1,68 @@
package com.zhangmeng.model.bean;
import com.alibaba.fastjson.JSON;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.stream.Collectors;
@Component
public class TokenTools {
//公钥
private static final String PUBLIC_KEY = "public.key";
private static String publickey="";
/***
*
* @return
*/
public Map<String,Object> getUserInfo(){
//获取授权信息
OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) SecurityContextHolder.getContext().getAuthentication().getDetails();
//令牌解码
return dcodeToken(details.getTokenValue());
}
/***
*
*/
public Map<String,Object> dcodeToken(String token){
//校验Jwt
Jwt jwt = JwtHelper.decodeAndVerify(token, new RsaVerifier(getPubKey()));
//获取Jwt原始内容
String claims = jwt.getClaims();
return JSON.parseObject(claims, Map.class);
}
/**
* Key
* @return Key
*/
public String getPubKey() {
if(!StringUtils.isEmpty(publickey)){
return publickey;
}
Resource resource = new ClassPathResource(PUBLIC_KEY);
try {
InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream());
BufferedReader br = new BufferedReader(inputStreamReader);
publickey = br.lines().collect(Collectors.joining("\n"));
return publickey;
} catch (IOException ioe) {
return null;
}
}
}