支持不同域的前后端分离部署

This commit is contained in:
648540858 2023-03-15 19:05:56 +08:00
parent 95688e400b
commit 5fab97cf7e
23 changed files with 226 additions and 155 deletions

View File

@ -14,7 +14,8 @@ import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.*; import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -48,13 +49,6 @@ public class ApiAccessFilter extends OncePerRequestFilter {
long start = System.currentTimeMillis(); // 请求进入时间 long start = System.currentTimeMillis(); // 请求进入时间
String uriName = ApiSaveConstant.getVal(servletRequest.getRequestURI()); String uriName = ApiSaveConstant.getVal(servletRequest.getRequestURI());
String origin = servletRequest.getHeader("Origin");
servletResponse.setContentType("application/json;charset=UTF-8");
servletResponse.setHeader("Access-Control-Allow-Origin", origin != null ? origin : "*");
servletResponse.setHeader("Access-Control-Allow-Credentials", "true");
servletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
servletResponse.setHeader("Access-Control-Max-Age", "3600");
servletResponse.setHeader("Access-Control-Allow-Headers", "token,Content-Type,Content-Length, Authorization, Accept,X-Requested-With,domain,zdy");
filterChain.doFilter(servletRequest, servletResponse); filterChain.doFilter(servletRequest, servletResponse);
if (uriName != null && userSetting != null && userSetting.getLogInDatebase() != null && userSetting.getLogInDatebase()) { if (uriName != null && userSetting != null && userSetting.getLogInDatebase() != null && userSetting.getLogInDatebase()) {

View File

@ -32,6 +32,17 @@ public class GlobalExceptionHandler {
return WVPResult.fail(ErrorCode.ERROR500.getCode(), e.getMessage()); return WVPResult.fail(ErrorCode.ERROR500.getCode(), e.getMessage());
} }
/**
* 默认异常处理
* @param e 异常
* @return 统一返回结果
*/
@ExceptionHandler(IllegalStateException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public WVPResult<String> exceptionHandler(IllegalStateException e) {
return WVPResult.fail(ErrorCode.ERROR400);
}
/** /**
* 自定义异常处理 处理controller中返回的错误 * 自定义异常处理 处理controller中返回的错误

View File

@ -55,6 +55,8 @@ public class UserSetting {
private List<String> interfaceAuthenticationExcludes = new ArrayList<>(); private List<String> interfaceAuthenticationExcludes = new ArrayList<>();
private List<String> allowedOrigins = new ArrayList<>();
public Boolean getSavePositionHistory() { public Boolean getSavePositionHistory() {
return savePositionHistory; return savePositionHistory;
} }
@ -218,4 +220,12 @@ public class UserSetting {
public void setSipLog(Boolean sipLog) { public void setSipLog(Boolean sipLog) {
this.sipLog = sipLog; this.sipLog = sipLog;
} }
public List<String> getAllowedOrigins() {
return allowedOrigins;
}
public void setAllowedOrigins(List<String> allowedOrigins) {
this.allowedOrigins = allowedOrigins;
}
} }

View File

@ -28,15 +28,6 @@ public class AnonymousAuthenticationEntryPoint implements AuthenticationEntry
String username = jwtUser.getUserName(); String username = jwtUser.getUserName();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword() ); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword() );
SecurityContextHolder.getContext().setAuthentication(token); SecurityContextHolder.getContext().setAuthentication(token);
System.out.println(jwt);
// 允许跨域
String origin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Origin", origin != null ? origin : "*");
response.setHeader("Access-Control-Allow-Methods", "PUT,POST, GET,DELETE,OPTIONS");
// 允许自定义请求头token(允许head跨域)
response.setHeader("Access-Control-Allow-Headers", "token, Accept, Origin, X-Requested-With, Content-Type, Last-Modified");
response.setHeader("Content-type", "application/json;charset=UTF-8");
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
jsonObject.put("code", ErrorCode.ERROR401.getCode()); jsonObject.put("code", ErrorCode.ERROR401.getCode());
jsonObject.put("msg", ErrorCode.ERROR401.getMsg()); jsonObject.put("msg", ErrorCode.ERROR401.getMsg());

View File

@ -24,15 +24,24 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
// 忽略登录请求的token验证
String requestURI = request.getRequestURI();
if (requestURI.equalsIgnoreCase("/api/user/login")) {
chain.doFilter(request, response);
return;
}
String jwt = request.getHeader(JwtUtils.getHeader()); String jwt = request.getHeader(JwtUtils.getHeader());
// 这里如果没有jwt继续往后走因为后面还有鉴权管理器等去判断是否拥有身份凭证所以是可以放行的 // 这里如果没有jwt继续往后走因为后面还有鉴权管理器等去判断是否拥有身份凭证所以是可以放行的
// 没有jwt相当于匿名访问若有一些接口是需要权限的则不能访问这些接口 // 没有jwt相当于匿名访问若有一些接口是需要权限的则不能访问这些接口
if (StringUtils.isBlank(jwt)) { if (StringUtils.isBlank(jwt)) {
chain.doFilter(request, response); jwt = request.getParameter(JwtUtils.getHeader());
return; if (StringUtils.isBlank(jwt)) {
chain.doFilter(request, response);
return;
}
} }
JwtUser jwtUser = JwtUtils.verifyToken(jwt); JwtUser jwtUser = JwtUtils.verifyToken(jwt);
String username = jwtUser.getUserName(); String username = jwtUser.getUserName();
// TODO 处理各个状态 // TODO 处理各个状态

View File

@ -23,7 +23,7 @@ public class JwtUtils {
private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class); private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
private static final String HEADER = "Access-Token"; private static final String HEADER = "access-token";
private static final String AUDIENCE = "Audience"; private static final String AUDIENCE = "Audience";
private static final long EXPIRED_THRESHOLD = 10 * 60; private static final long EXPIRED_THRESHOLD = 10 * 60;

View File

@ -27,16 +27,13 @@ public class SecurityUtils {
public static LoginUser login(String username, String password, AuthenticationManager authenticationManager) throws AuthenticationException { public static LoginUser login(String username, String password, AuthenticationManager authenticationManager) throws AuthenticationException {
//使用security框架自带的验证token生成器 也可以自定义 //使用security框架自带的验证token生成器 也可以自定义
UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username,password); UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username,password);
// Authentication authenticate = authenticationManager.authenticate(token); //认证 如果失败这里会自动异常后返回所以这里不需要判断返回值是否为空确定是否登录成功
// SecurityContextHolder.getContext().setAuthentication(authenticate); Authentication authenticate = authenticationManager.authenticate(token);
LoginUser user = (LoginUser) authenticate.getPrincipal();
SecurityContextHolder.getContext().setAuthentication(token); SecurityContextHolder.getContext().setAuthentication(token);
return user;
// LoginUser user = (LoginUser) authenticate.getPrincipal();
User user = new User();
user.setUsername(username);
LoginUser loginUser = new LoginUser(user, LocalDateTime.now());
return loginUser;
} }
/** /**

View File

@ -18,8 +18,13 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.List; import java.util.ArrayList;
import java.util.Arrays;
/** /**
* 配置Spring Security * 配置Spring Security
@ -61,12 +66,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter; private JwtAuthenticationFilter jwtAuthenticationFilter;
// @Bean
// JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
// JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
// return jwtAuthenticationFilter;
// }
/** /**
* 描述: 静态资源放行这里的放行是不走 Spring Security 过滤器链 * 描述: 静态资源放行这里的放行是不走 Spring Security 过滤器链
@ -77,27 +76,19 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
if (!userSetting.isInterfaceAuthentication()) { if (!userSetting.isInterfaceAuthentication()) {
web.ignoring().antMatchers("**"); web.ignoring().antMatchers("**");
}else { }else {
ArrayList<String> matchers = new ArrayList<>();
matchers.add("/");
matchers.add("/#/**");
matchers.add("/static/**");
matchers.add("/index.html");
matchers.add("/doc.html");
matchers.add("/webjars/**");
matchers.add("/swagger-resources/**");
matchers.add("/v3/api-docs/**");
matchers.add("/js/**");
matchers.addAll(userSetting.getInterfaceAuthenticationExcludes());
// 可以直接访问的静态数据 // 可以直接访问的静态数据
web.ignoring() web.ignoring().antMatchers(matchers.toArray(new String[0]));
.antMatchers("/")
.antMatchers("/#/**")
.antMatchers("/static/**")
.antMatchers("/index.html")
.antMatchers("/doc.html") // "/webjars/**", "/swagger-resources/**", "/v3/api-docs/**"
.antMatchers("/webjars/**")
.antMatchers("/swagger-resources/**")
.antMatchers("/v3/api-docs/**")
.antMatchers("/favicon.ico")
.antMatchers("/js/**");
List<String> interfaceAuthenticationExcludes = userSetting.getInterfaceAuthenticationExcludes();
for (String interfaceAuthenticationExclude : interfaceAuthenticationExcludes) {
if (interfaceAuthenticationExclude.split("/").length < 4 ) {
logger.warn("{}不满足两级目录,已忽略", interfaceAuthenticationExclude);
}else {
web.ignoring().antMatchers(interfaceAuthenticationExclude);
}
}
} }
} }
@ -121,7 +112,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http.headers().contentTypeOptions().disable() http.headers().contentTypeOptions().disable()
.and().cors() .and().cors().configurationSource(configurationSource())
.and().csrf().disable() .and().csrf().disable()
.sessionManagement() .sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
@ -129,50 +120,36 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// 配置拦截规则 // 配置拦截规则
.and() .and()
.authorizeRequests() .authorizeRequests()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll()
.antMatchers("/api/user/login","/index/hook/**").permitAll() .antMatchers("/api/user/login","/index/hook/**").permitAll()
.anyRequest().authenticated() .anyRequest().authenticated()
// 异常处理器 // 异常处理器
.and() .and()
.exceptionHandling() .exceptionHandling()
.authenticationEntryPoint(anonymousAuthenticationEntryPoint) .authenticationEntryPoint(anonymousAuthenticationEntryPoint)
// .accessDeniedHandler(jwtAccessDeniedHandler) .and().logout().logoutUrl("/api/user/logout").permitAll()
// 配置自定义的过滤器 .logoutSuccessHandler(logoutHandler)
// .and()
// .addFilter(jwtAuthenticationFilter)
// 验证码过滤器放在UsernamePassword过滤器之前
// .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)
; ;
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
// // 设置允许添加静态文件
// http.headers().contentTypeOptions().disable();
// http.authorizeRequests()
// // 放行接口
// .antMatchers("/api/user/login","/index/hook/**").permitAll()
// // 除上面外的所有请求全部需要鉴权认证
// .anyRequest().authenticated()
// // 禁用session
// .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
// // 异常处理(权限拒绝登录失效等)
// .and().exceptionHandling()
// // 匿名用户访问无权限资源时的异常处理
// .authenticationEntryPoint(anonymousAuthenticationEntryPoint)
// // 登录 允许所有用户
// .and().formLogin()
// // 登录成功处理逻辑 在这里给出JWT
// .successHandler(loginSuccessHandler)
// // 登录失败处理逻辑
// .failureHandler(loginFailureHandler)
// // 登出
// .and().logout().logoutUrl("/api/user/logout").permitAll()
// // 登出成功处理逻辑
// .logoutSuccessHandler(logoutHandler)
// // 配置自定义的过滤器
// .and()
// .addFilter(jwtAuthenticationFilter())
// ;
} }
CorsConfigurationSource configurationSource(){
// 配置跨域
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
corsConfiguration.setAllowedMethods(Arrays.asList("*"));
corsConfiguration.setMaxAge(3600L);
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setAllowedOrigins(userSetting.getAllowedOrigins());
corsConfiguration.setExposedHeaders(Arrays.asList(JwtUtils.getHeader()));
UrlBasedCorsConfigurationSource url = new UrlBasedCorsConfigurationSource();
url.registerCorsConfiguration("/**",corsConfiguration);
return url;
}
/** /**
* 描述: 密码加密算法 BCrypt 推荐使用 * 描述: 密码加密算法 BCrypt 推荐使用
**/ **/

View File

@ -28,6 +28,10 @@ public class WVPResult<T> implements Cloneable{
return new WVPResult<>(ErrorCode.SUCCESS.getCode(), msg, t); return new WVPResult<>(ErrorCode.SUCCESS.getCode(), msg, t);
} }
public static WVPResult success() {
return new WVPResult<>(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
}
public static <T> WVPResult<T> success(T t) { public static <T> WVPResult<T> success(T t) {
return success(t, ErrorCode.SUCCESS.getMsg()); return success(t, ErrorCode.SUCCESS.getMsg());
} }

View File

@ -31,7 +31,6 @@ import java.text.ParseException;
import java.util.UUID; import java.util.UUID;
@Tag(name = "国标设备配置") @Tag(name = "国标设备配置")
@RestController @RestController
@RequestMapping("/api/device/config") @RequestMapping("/api/device/config")
public class DeviceConfig { public class DeviceConfig {

View File

@ -24,6 +24,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.compress.utils.IOUtils;
import org.apache.ibatis.annotations.Options;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -97,8 +98,10 @@ public class DeviceQuery {
@Parameter(name = "page", description = "当前页", required = true) @Parameter(name = "page", description = "当前页", required = true)
@Parameter(name = "count", description = "每页查询数量", required = true) @Parameter(name = "count", description = "每页查询数量", required = true)
@GetMapping("/devices") @GetMapping("/devices")
@Options()
public PageInfo<Device> devices(int page, int count){ public PageInfo<Device> devices(int page, int count){
// if (page == null) page = 0;
// if (count == null) count = 20;
return storager.queryVideoDeviceList(page, count,null); return storager.queryVideoDeviceList(page, count,null);
} }

View File

@ -23,7 +23,6 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -70,9 +69,6 @@ public class ServerController {
private int serverPort; private int serverPort;
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@Autowired @Autowired
private IRedisCatchStorage redisCatchStorage; private IRedisCatchStorage redisCatchStorage;

View File

@ -27,7 +27,6 @@ import javax.servlet.http.HttpServletResponse;
import java.util.List; import java.util.List;
@Tag(name = "用户管理") @Tag(name = "用户管理")
@RestController @RestController
@RequestMapping("/api/user") @RequestMapping("/api/user")
public class UserController { public class UserController {
@ -47,7 +46,7 @@ public class UserController {
@Parameter(name = "username", description = "用户名", required = true) @Parameter(name = "username", description = "用户名", required = true)
@Parameter(name = "password", description = "密码32位md5加密", required = true) @Parameter(name = "password", description = "密码32位md5加密", required = true)
public LoginUser login(HttpServletRequest request, HttpServletResponse response, @RequestParam String username, @RequestParam String password){ public LoginUser login(HttpServletRequest request, HttpServletResponse response, @RequestParam String username, @RequestParam String password){
LoginUser user = null; LoginUser user;
try { try {
user = SecurityUtils.login(username, password, authenticationManager); user = SecurityUtils.login(username, password, authenticationManager);
} catch (AuthenticationException e) { } catch (AuthenticationException e) {
@ -62,6 +61,25 @@ public class UserController {
return user; return user;
} }
// @GetMapping("/logout")
// @PostMapping("/logout")
// @Operation(summary = "登出")
// public LoginUser logout(){
// LoginUser user;
// try {
// user = SecurityUtils.login(username, password, authenticationManager);
// } catch (AuthenticationException e) {
// throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
// }
// if (user == null) {
// throw new ControllerException(ErrorCode.ERROR100.getCode(), "用户名或密码错误");
// }else {
// String jwt = JwtUtils.createToken(username, password);
// response.setHeader(JwtUtils.getHeader(), jwt);
// }
// return user;
// }
@PostMapping("/changePassword") @PostMapping("/changePassword")
@Operation(summary = "修改密码") @Operation(summary = "修改密码")
@Parameter(name = "username", description = "用户名", required = true) @Parameter(name = "username", description = "用户名", required = true)

View File

@ -201,6 +201,10 @@ user-settings:
sip-log: true sip-log: true
# 自动数据库升级,保证表结构完整 # 自动数据库升级,保证表结构完整
sync-db: true sync-db: true
# 跨域配置,配置你访问前端页面的地址即可, 可以配置多个
allowed-origins:
- http://localhost:8008
- http://192.168.1.3:8008
# 关闭在线文档(生产环境建议关闭) # 关闭在线文档(生产环境建议关闭)
springdoc: springdoc:

View File

@ -23,7 +23,7 @@
"vue-clipboard2": "^0.3.1", "vue-clipboard2": "^0.3.1",
"vue-clipboards": "^1.3.0", "vue-clipboards": "^1.3.0",
"vue-contextmenujs": "^1.3.13", "vue-contextmenujs": "^1.3.13",
"vue-cookies": "^1.7.4", "vue-cookies": "^1.8.3",
"vue-giant-tree": "^0.1.5", "vue-giant-tree": "^0.1.5",
"vue-router": "^3.1.6", "vue-router": "^3.1.6",
"vue-ztree-2.0": "^1.0.4" "vue-ztree-2.0": "^1.0.4"
@ -13135,9 +13135,9 @@
"integrity": "sha1-O9rgI8e9QgleeNpCWAACUNUKuO8=" "integrity": "sha1-O9rgI8e9QgleeNpCWAACUNUKuO8="
}, },
"node_modules/vue-cookies": { "node_modules/vue-cookies": {
"version": "1.7.4", "version": "1.8.3",
"resolved": "https://registry.npm.taobao.org/vue-cookies/download/vue-cookies-1.7.4.tgz?cache=0&sync_timestamp=1598941352058&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-cookies%2Fdownload%2Fvue-cookies-1.7.4.tgz", "resolved": "https://registry.npmmirror.com/vue-cookies/-/vue-cookies-1.8.3.tgz",
"integrity": "sha1-0kHQoEMdoHlYN2UdELTXPnyNPo0=" "integrity": "sha512-VBRsyRMVdahBgFfh389TMHPmDdr4URDJNMk4FKSCfuNITs7+jitBDhwyL4RJd3WUsfOYNNjPAkfbehyH9AFuoA=="
}, },
"node_modules/vue-giant-tree": { "node_modules/vue-giant-tree": {
"version": "0.1.5", "version": "0.1.5",
@ -25489,9 +25489,9 @@
"integrity": "sha1-O9rgI8e9QgleeNpCWAACUNUKuO8=" "integrity": "sha1-O9rgI8e9QgleeNpCWAACUNUKuO8="
}, },
"vue-cookies": { "vue-cookies": {
"version": "1.7.4", "version": "1.8.3",
"resolved": "https://registry.npm.taobao.org/vue-cookies/download/vue-cookies-1.7.4.tgz?cache=0&sync_timestamp=1598941352058&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-cookies%2Fdownload%2Fvue-cookies-1.7.4.tgz", "resolved": "https://registry.npmmirror.com/vue-cookies/-/vue-cookies-1.8.3.tgz",
"integrity": "sha1-0kHQoEMdoHlYN2UdELTXPnyNPo0=" "integrity": "sha512-VBRsyRMVdahBgFfh389TMHPmDdr4URDJNMk4FKSCfuNITs7+jitBDhwyL4RJd3WUsfOYNNjPAkfbehyH9AFuoA=="
}, },
"vue-giant-tree": { "vue-giant-tree": {
"version": "0.1.5", "version": "0.1.5",

View File

@ -25,7 +25,7 @@
"vue-clipboard2": "^0.3.1", "vue-clipboard2": "^0.3.1",
"vue-clipboards": "^1.3.0", "vue-clipboards": "^1.3.0",
"vue-contextmenujs": "^1.3.13", "vue-contextmenujs": "^1.3.13",
"vue-cookies": "^1.7.4", "vue-cookies": "^1.8.3",
"vue-giant-tree": "^0.1.5", "vue-giant-tree": "^0.1.5",
"vue-router": "^3.1.6", "vue-router": "^3.1.6",
"vue-ztree-2.0": "^1.0.4" "vue-ztree-2.0": "^1.0.4"

View File

@ -5,6 +5,7 @@
</template> </template>
<script> <script>
import userService from './components/service/UserService'
export default { export default {
name: 'app', name: 'app',
data(){ data(){
@ -19,7 +20,7 @@ export default {
} }
}, },
created() { created() {
if(!this.$cookies.get("session")){ if (userService.getToken() == null){
// //
this.$router.push('/login'); this.$router.push('/login');
} }
@ -33,28 +34,14 @@ export default {
// this.getUserInfo(); // this.getUserInfo();
}, },
methods: { methods: {
//
getUserInfo(){
var userinfo = this.$cookies.get("session");
},
checkLogin(){ checkLogin(){
//session //session
//cookie if (userService.getToken() == null){
if(!this.$cookies.get("session")){
// //
this.$router.push('/login'); // this.$router.push('/login');
} }
}, },
getCookie: function (cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1);
if (c.indexOf(name) != -1) return c.substring(name.length, c.length);
}
return "";
}
}, },
components: {} components: {}
}; };

View File

@ -35,6 +35,7 @@
<script> <script>
import crypto from 'crypto' import crypto from 'crypto'
import userService from "./service/UserService";
export default { export default {
name: 'Login', name: 'Login',
data(){ data(){
@ -85,9 +86,10 @@ export default {
params: loginParam params: loginParam
}).then(function (res) { }).then(function (res) {
window.clearTimeout(timeoutTask) window.clearTimeout(timeoutTask)
console.log(JSON.stringify(res)); console.log(res);
console.log("登录成功");
if (res.data.code === 0 ) { if (res.data.code === 0 ) {
that.$cookies.set("session", {"username": that.username,"roleId":res.data.data.role.id}) ; userService.setUser(res.data.data)
// //
that.cancelEnterkeyDefaultAction(); that.cancelEnterkeyDefaultAction();
that.$router.push('/'); that.$router.push('/');
@ -106,14 +108,6 @@ export default {
that.isLoging = false; that.isLoging = false;
}); });
}, },
setCookie: function (cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toUTCString();
console.info(cname + "=" + cvalue + "; " + expires);
document.cookie = cname + "=" + cvalue + "; " + expires;
console.info(document.cookie);
},
cancelEnterkeyDefaultAction: function() { cancelEnterkeyDefaultAction: function() {
document.onkeydown = function(e) { document.onkeydown = function(e) {
var key = window.event.keyCode; var key = window.event.keyCode;

View File

@ -35,6 +35,7 @@
<script> <script>
import crypto from 'crypto' import crypto from 'crypto'
import userService from "../service/UserService";
export default { export default {
name: "changePassword", name: "changePassword",
props: {}, props: {},
@ -105,7 +106,7 @@ export default {
this.showDialog = false; this.showDialog = false;
setTimeout(()=>{ setTimeout(()=>{
// cookie // cookie
this.$cookies.remove("session"); userService.clearUserInfo();
this.$router.push('/login'); this.$router.push('/login');
this.sseSource.close(); this.sseSource.close();
},800) },800)

View File

@ -16,6 +16,7 @@
drag drag
:action="uploadUrl" :action="uploadUrl"
name="file" name="file"
:headers="headers"
:on-success="successHook" :on-success="successHook"
:on-error="errorHook" :on-error="errorHook"
> >
@ -33,6 +34,8 @@
import ShowErrorData from './importChannelShowErrorData.vue' import ShowErrorData from './importChannelShowErrorData.vue'
import userService from "../service/UserService";
export default { export default {
name: "importChannel", name: "importChannel",
components: { components: {
@ -47,7 +50,10 @@ export default {
isEdit: false, isEdit: false,
errorStreams: [], errorStreams: [],
errorGBIds: [], errorGBIds: [],
uploadUrl: process.env.NODE_ENV === 'development'?`debug/api/push/upload`:`api/push/upload`, headers: {
"access-token": userService.getToken()
},
uploadUrl: process.env.NODE_ENV === 'development'? `http://127.0.0.1:8080/debug/api/push/upload`: (window.baseUrl ? window.baseUrl : "") + `/api/push/upload`,
}; };
}, },
methods: { methods: {

View File

@ -0,0 +1,42 @@
export default {
/**
* 存储用户信息
* @param username
* @param token
*/
setUser(user){
localStorage.setItem("wvp-user", JSON.stringify(user));
},
/**
* 获取用户
*/
getUser(){
return JSON.parse(localStorage.getItem("wvp-user"));
},
/**
* 获取登录token
*/
getToken(){
return localStorage.getItem("wvp-token");
},
/**
* 清理用户信息
*/
clearUserInfo(){
localStorage.removeItem("wvp-user");
localStorage.removeItem("wvp-token");
},
/**
* 更新token
* @param header
*/
setToken(token) {
localStorage.setItem("wvp-token", token);
}
}

View File

@ -23,9 +23,9 @@
<!-- </el-submenu>--> <!-- </el-submenu>-->
<!-- <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>--> <!-- <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>-->
<el-submenu index="" style="float: right;"> <el-submenu index="" style="float: right;">
<template slot="title">欢迎{{ this.$cookies.get("session").username }}</template> <template slot="title">欢迎{{ username }}</template>
<el-menu-item @click="openDoc">在线文档</el-menu-item> <el-menu-item @click="openDoc">在线文档</el-menu-item>
<el-menu-item > <el-menu-item>
<el-switch v-model="alarmNotify" inactive-text="报警信息推送" @change="alarmNotifyChannge"></el-switch> <el-switch v-model="alarmNotify" inactive-text="报警信息推送" @change="alarmNotifyChannge"></el-switch>
</el-menu-item> </el-menu-item>
<el-menu-item @click="changePassword">修改密码</el-menu-item> <el-menu-item @click="changePassword">修改密码</el-menu-item>
@ -39,6 +39,7 @@
<script> <script>
import changePasswordDialog from '../components/dialog/changePassword.vue' import changePasswordDialog from '../components/dialog/changePassword.vue'
import userService from '../components/service/UserService'
export default { export default {
name: "UiHeader", name: "UiHeader",
@ -47,14 +48,17 @@ export default {
return { return {
alarmNotify: false, alarmNotify: false,
sseSource: null, sseSource: null,
username: userService.getUser().username,
activeIndex: this.$route.path, activeIndex: this.$route.path,
editUser: this.$cookies.get("session").roleId==1 editUser: userService.getUser() ? userService.getUser().role.id === 1 : false
}; };
}, },
created() { created() {
console.log(this.$cookies.get("session")) console.log(4444)
console.log(JSON.stringify(userService.getUser()))
if (this.$route.path.startsWith("/channelList")) { if (this.$route.path.startsWith("/channelList")) {
this.activeIndex = "/deviceList" this.activeIndex = "/deviceList"
} }
}, },
mounted() { mounted() {
@ -69,10 +73,13 @@ export default {
method: 'get', method: 'get',
url: "/api/user/logout" url: "/api/user/logout"
}).then((res) => { }).then((res) => {
// cookie //
this.$cookies.remove("session"); userService.clearUserInfo()
this.$router.push('/login'); this.$router.push('/login');
this.sseSource.close(); if (this.sseSource != null) {
this.sseSource.close();
}
}).catch((error) => { }).catch((error) => {
console.error("登出失败") console.error("登出失败")
console.error(error) console.error(error)
@ -151,16 +158,19 @@ export default {
</script> </script>
<style> <style>
#UiHeader .el-switch__label { #UiHeader .el-switch__label {
color: white ; color: white;
} }
.el-menu--popup .el-menu-item .el-switch .el-switch__label { .el-menu--popup .el-menu-item .el-switch .el-switch__label {
color: white !important; color: white !important;
} }
#UiHeader .el-switch__label.is-active{
#UiHeader .el-switch__label.is-active {
color: #409EFF; color: #409EFF;
} }
#UiHeader .el-menu-item.is-active { #UiHeader .el-menu-item.is-active {
color: #fff!important; color: #fff !important;
background-color: #1890ff!important; background-color: #1890ff !important;
} }
</style> </style>

View File

@ -1,5 +1,6 @@
import Vue from 'vue'; import Vue from 'vue';
import App from './App.vue'; import App from './App.vue';
Vue.config.productionTip = false; Vue.config.productionTip = false;
import ElementUI from 'element-ui'; import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css'; import 'element-ui/lib/theme-chalk/index.css';
@ -10,15 +11,16 @@ import echarts from 'echarts';
import VCharts from 'v-charts'; import VCharts from 'v-charts';
import VueClipboard from 'vue-clipboard2'; import VueClipboard from 'vue-clipboard2';
import { Notification } from 'element-ui'; import {Notification} from 'element-ui';
import Fingerprint2 from 'fingerprintjs2'; import Fingerprint2 from 'fingerprintjs2';
import VueClipboards from 'vue-clipboards'; import VueClipboards from 'vue-clipboards';
import Contextmenu from "vue-contextmenujs" import Contextmenu from "vue-contextmenujs"
import userService from "./components/service/UserService"
// 生成唯一ID // 生成唯一ID
Fingerprint2.get(function(components) { Fingerprint2.get(function (components) {
const values = components.map(function(component,index) { const values = components.map(function (component, index) {
if (index === 0) { //把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样 if (index === 0) { //把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样
return component.value.replace(/\bNetType\/\w+\b/, ''); return component.value.replace(/\bNetType\/\w+\b/, '');
} }
@ -42,13 +44,17 @@ Vue.prototype.$notify = Notification;
Vue.use(Contextmenu); Vue.use(Contextmenu);
Vue.use(VCharts); Vue.use(VCharts);
axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : (window.baseUrl?window.baseUrl:""); axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : (window.baseUrl ? window.baseUrl : "");
axios.defaults.withCredentials = true; axios.defaults.withCredentials = true;
// api 返回401自动回登陆页面 // api 返回401自动回登陆页面
axios.interceptors.response.use(function (response) { axios.interceptors.response.use((response) => {
// 对响应数据做点什么 // 对响应数据做点什么
let token = response.headers["access-token"];
if (token) {
userService.setToken(token)
}
return response; return response;
}, function (error) { }, (error) => {
// 对响应错误做点什么 // 对响应错误做点什么
if (error.response.status === 401) { if (error.response.status === 401) {
console.log("Received 401 Response") console.log("Received 401 Response")
@ -56,10 +62,22 @@ axios.interceptors.response.use(function (response) {
} }
return Promise.reject(error); return Promise.reject(error);
}); });
axios.interceptors.request.use(
config => {
if (userService.getToken() != null && config.url !== "/api/user/login") {
config.headers['access-token'] = `${userService.getToken()}`;
}
return config;
},
error => {
return Promise.reject(error);
}
);
Vue.prototype.$axios = axios; Vue.prototype.$axios = axios;
Vue.prototype.$cookies.config(60*30); Vue.prototype.$cookies.config(60*30);
new Vue({ new Vue({
router: router, router: router,
render: h => h(App), render: h => h(App),
}).$mount('#app') }).$mount('#app')