浏览代码

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

648540858 2 年之前
父节点
当前提交
5fab97cf7e
共有 23 个文件被更改,包括 226 次插入155 次删除
  1. 2 8
      src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java
  2. 11 0
      src/main/java/com/genersoft/iot/vmp/conf/GlobalExceptionHandler.java
  3. 10 0
      src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
  4. 0 9
      src/main/java/com/genersoft/iot/vmp/conf/security/AnonymousAuthenticationEntryPoint.java
  5. 12 3
      src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java
  6. 1 1
      src/main/java/com/genersoft/iot/vmp/conf/security/JwtUtils.java
  7. 5 8
      src/main/java/com/genersoft/iot/vmp/conf/security/SecurityUtils.java
  8. 38 61
      src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
  9. 4 0
      src/main/java/com/genersoft/iot/vmp/vmanager/bean/WVPResult.java
  10. 0 1
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java
  11. 4 1
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
  12. 0 4
      src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
  13. 20 2
      src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
  14. 4 0
      src/main/resources/all-application.yml
  15. 7 7
      web_src/package-lock.json
  16. 1 1
      web_src/package.json
  17. 5 18
      web_src/src/App.vue
  18. 4 10
      web_src/src/components/Login.vue
  19. 2 1
      web_src/src/components/dialog/changePassword.vue
  20. 7 1
      web_src/src/components/dialog/importChannel.vue
  21. 42 0
      web_src/src/components/service/UserService.js
  22. 21 11
      web_src/src/layout/UiHeader.vue
  23. 26 8
      web_src/src/main.js

+ 2 - 8
src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java

@@ -14,7 +14,8 @@ import org.springframework.stereotype.Component;
 import org.springframework.util.ObjectUtils;
 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.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -48,13 +49,6 @@ public class ApiAccessFilter extends OncePerRequestFilter {
         long start = System.currentTimeMillis(); // 请求进入时间
         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);
 
         if (uriName != null && userSetting != null && userSetting.getLogInDatebase() != null && userSetting.getLogInDatebase()) {

+ 11 - 0
src/main/java/com/genersoft/iot/vmp/conf/GlobalExceptionHandler.java

@@ -32,6 +32,17 @@ public class GlobalExceptionHandler {
         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中返回的错误

+ 10 - 0
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java

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

+ 0 - 9
src/main/java/com/genersoft/iot/vmp/conf/security/AnonymousAuthenticationEntryPoint.java

@@ -28,15 +28,6 @@ public class    AnonymousAuthenticationEntryPoint implements AuthenticationEntry
         String username = jwtUser.getUserName();
         UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword() );
         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.put("code", ErrorCode.ERROR401.getCode());
         jsonObject.put("msg", ErrorCode.ERROR401.getMsg());

+ 12 - 3
src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java

@@ -24,15 +24,24 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
 
     @Override
     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());
         // 这里如果没有jwt,继续往后走,因为后面还有鉴权管理器等去判断是否拥有身份凭证,所以是可以放行的
         // 没有jwt相当于匿名访问,若有一些接口是需要权限的,则不能访问这些接口
         if (StringUtils.isBlank(jwt)) {
-            chain.doFilter(request, response);
-            return;
+            jwt = request.getParameter(JwtUtils.getHeader());
+            if (StringUtils.isBlank(jwt)) {
+                chain.doFilter(request, response);
+                return;
+            }
         }
 
-
         JwtUser jwtUser = JwtUtils.verifyToken(jwt);
         String username = jwtUser.getUserName();
         // TODO 处理各个状态

+ 1 - 1
src/main/java/com/genersoft/iot/vmp/conf/security/JwtUtils.java

@@ -23,7 +23,7 @@ public class JwtUtils {
 
     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 long EXPIRED_THRESHOLD = 10 * 60;

+ 5 - 8
src/main/java/com/genersoft/iot/vmp/conf/security/SecurityUtils.java

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

+ 38 - 61
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java

@@ -18,8 +18,13 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
 import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 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
@@ -61,12 +66,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
     @Autowired
     private JwtAuthenticationFilter jwtAuthenticationFilter;
 
-//    @Bean
-//    JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
-//        JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
-//        return jwtAuthenticationFilter;
-//    }
-
 
     /**
      * 描述: 静态资源放行,这里的放行,是不走 Spring Security 过滤器链
@@ -77,27 +76,19 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
         if (!userSetting.isInterfaceAuthentication()) {
             web.ignoring().antMatchers("**");
         }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()
-                    .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);
-                }
-
-            }
+            web.ignoring().antMatchers(matchers.toArray(new String[0]));
         }
     }
 
@@ -121,7 +112,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
     @Override
     protected void configure(HttpSecurity http) throws Exception {
         http.headers().contentTypeOptions().disable()
-                .and().cors()
+                .and().cors().configurationSource(configurationSource())
                 .and().csrf().disable()
                 .sessionManagement()
                 .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
@@ -129,50 +120,36 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 // 配置拦截规则
                 .and()
                 .authorizeRequests()
+                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
+                .antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll()
                 .antMatchers("/api/user/login","/index/hook/**").permitAll()
                 .anyRequest().authenticated()
                 // 异常处理器
                 .and()
                 .exceptionHandling()
                 .authenticationEntryPoint(anonymousAuthenticationEntryPoint)
-//                .accessDeniedHandler(jwtAccessDeniedHandler)
-                // 配置自定义的过滤器
-//                .and()
-//                .addFilter(jwtAuthenticationFilter)
-                // 验证码过滤器放在UsernamePassword过滤器之前
-//                .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)
+                .and().logout().logoutUrl("/api/user/logout").permitAll()
+                .logoutSuccessHandler(logoutHandler)
         ;
         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 推荐使用
      **/

+ 4 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/bean/WVPResult.java

@@ -28,6 +28,10 @@ public class WVPResult<T> implements Cloneable{
         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) {
         return success(t, ErrorCode.SUCCESS.getMsg());
     }

+ 0 - 1
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java

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

+ 4 - 1
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java

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

+ 0 - 4
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java

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

+ 20 - 2
src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java

@@ -27,7 +27,6 @@ import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @Tag(name  = "用户管理")
-
 @RestController
 @RequestMapping("/api/user")
 public class UserController {
@@ -47,7 +46,7 @@ public class UserController {
     @Parameter(name = "username", description = "用户名", required = true)
     @Parameter(name = "password", description = "密码(32位md5加密)", required = true)
     public LoginUser login(HttpServletRequest request, HttpServletResponse response, @RequestParam String username, @RequestParam String password){
-        LoginUser user = null;
+        LoginUser user;
         try {
             user = SecurityUtils.login(username, password, authenticationManager);
         } catch (AuthenticationException e) {
@@ -62,6 +61,25 @@ public class UserController {
         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")
     @Operation(summary = "修改密码")
     @Parameter(name = "username", description = "用户名", required = true)

+ 4 - 0
src/main/resources/all-application.yml

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

+ 7 - 7
web_src/package-lock.json

@@ -23,7 +23,7 @@
         "vue-clipboard2": "^0.3.1",
         "vue-clipboards": "^1.3.0",
         "vue-contextmenujs": "^1.3.13",
-        "vue-cookies": "^1.7.4",
+        "vue-cookies": "^1.8.3",
         "vue-giant-tree": "^0.1.5",
         "vue-router": "^3.1.6",
         "vue-ztree-2.0": "^1.0.4"
@@ -13135,9 +13135,9 @@
       "integrity": "sha1-O9rgI8e9QgleeNpCWAACUNUKuO8="
     },
     "node_modules/vue-cookies": {
-      "version": "1.7.4",
-      "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",
-      "integrity": "sha1-0kHQoEMdoHlYN2UdELTXPnyNPo0="
+      "version": "1.8.3",
+      "resolved": "https://registry.npmmirror.com/vue-cookies/-/vue-cookies-1.8.3.tgz",
+      "integrity": "sha512-VBRsyRMVdahBgFfh389TMHPmDdr4URDJNMk4FKSCfuNITs7+jitBDhwyL4RJd3WUsfOYNNjPAkfbehyH9AFuoA=="
     },
     "node_modules/vue-giant-tree": {
       "version": "0.1.5",
@@ -25489,9 +25489,9 @@
       "integrity": "sha1-O9rgI8e9QgleeNpCWAACUNUKuO8="
     },
     "vue-cookies": {
-      "version": "1.7.4",
-      "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",
-      "integrity": "sha1-0kHQoEMdoHlYN2UdELTXPnyNPo0="
+      "version": "1.8.3",
+      "resolved": "https://registry.npmmirror.com/vue-cookies/-/vue-cookies-1.8.3.tgz",
+      "integrity": "sha512-VBRsyRMVdahBgFfh389TMHPmDdr4URDJNMk4FKSCfuNITs7+jitBDhwyL4RJd3WUsfOYNNjPAkfbehyH9AFuoA=="
     },
     "vue-giant-tree": {
       "version": "0.1.5",

+ 1 - 1
web_src/package.json

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

+ 5 - 18
web_src/src/App.vue

@@ -5,6 +5,7 @@
 </template>
 
 <script>
+import  userService from './components/service/UserService'
 export default {
   name: 'app',
   data(){
@@ -19,7 +20,7 @@ export default {
     }
   },
   created() {
-    if(!this.$cookies.get("session")){
+    if (userService.getToken() == null){
       //如果没有登录状态则跳转到登录页
       this.$router.push('/login');
     }
@@ -33,28 +34,14 @@ export default {
     // this.getUserInfo();
   },
   methods: {
-    //请求用户的一些信息
-    getUserInfo(){
-      var userinfo = this.$cookies.get("session");
-    },
     checkLogin(){
       //检查是否存在session
-      //cookie操作方法在源码里有或者参考网上的即可
-      if(!this.$cookies.get("session")){
+      if (userService.getToken() == null){
         //如果没有登录状态则跳转到登录页
-        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: {}
 };

+ 4 - 10
web_src/src/components/Login.vue

@@ -35,6 +35,7 @@
 
 <script>
 import crypto from 'crypto'
+import userService from "./service/UserService";
 export default {
   name: 'Login',
   data(){
@@ -85,9 +86,10 @@ export default {
         params: loginParam
       }).then(function (res) {
         window.clearTimeout(timeoutTask)
-        console.log(JSON.stringify(res));
+        console.log(res);
+        console.log("登录成功");
           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.$router.push('/');
@@ -106,14 +108,6 @@ export default {
         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() {
         document.onkeydown = function(e) {
         var key = window.event.keyCode;

+ 2 - 1
web_src/src/components/dialog/changePassword.vue

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

+ 7 - 1
web_src/src/components/dialog/importChannel.vue

@@ -16,6 +16,7 @@
           drag
           :action="uploadUrl"
           name="file"
+          :headers="headers"
           :on-success="successHook"
           :on-error="errorHook"
           >
@@ -33,6 +34,8 @@
 
 import ShowErrorData from './importChannelShowErrorData.vue'
 
+import userService from "../service/UserService";
+
 export default {
   name: "importChannel",
   components: {
@@ -47,7 +50,10 @@ export default {
       isEdit: false,
       errorStreams: [],
       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: {

+ 42 - 0
web_src/src/components/service/UserService.js

@@ -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);
+  }
+}

+ 21 - 11
web_src/src/layout/UiHeader.vue

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

+ 26 - 8
web_src/src/main.js

@@ -1,5 +1,6 @@
 import Vue from 'vue';
 import App from './App.vue';
+
 Vue.config.productionTip = false;
 import ElementUI from 'element-ui';
 import 'element-ui/lib/theme-chalk/index.css';
@@ -10,15 +11,16 @@ import echarts from 'echarts';
 import VCharts from 'v-charts';
 
 import VueClipboard from 'vue-clipboard2';
-import { Notification } from 'element-ui';
+import {Notification} from 'element-ui';
 import Fingerprint2 from 'fingerprintjs2';
 import VueClipboards from 'vue-clipboards';
 import Contextmenu from "vue-contextmenujs"
+import userService from "./components/service/UserService"
 
 
 // 生成唯一ID
-Fingerprint2.get(function(components) {
-  const values = components.map(function(component,index) {
+Fingerprint2.get(function (components) {
+  const values = components.map(function (component, index) {
     if (index === 0) { //把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样
       return component.value.replace(/\bNetType\/\w+\b/, '');
     }
@@ -42,13 +44,17 @@ Vue.prototype.$notify = Notification;
 Vue.use(Contextmenu);
 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;
 // 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;
-}, function (error) {
+}, (error) => {
   // 对响应错误做点什么
   if (error.response.status === 401) {
     console.log("Received 401 Response")
@@ -56,10 +62,22 @@ axios.interceptors.response.use(function (response) {
   }
   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.$cookies.config(60*30);
 
 new Vue({
-	router: router,
-	render: h => h(App),
+  router: router,
+  render: h => h(App),
 }).$mount('#app')