Commit cb5849d8a14f55241c44bdf6724b18de7950564d
1 parent
123ce171
支持接口鉴权,支持修改密码,
Showing
20 changed files
with
752 additions
and
16 deletions
pom.xml
| @@ -67,6 +67,10 @@ | @@ -67,6 +67,10 @@ | ||
| 67 | <artifactId>mybatis-spring-boot-starter</artifactId> | 67 | <artifactId>mybatis-spring-boot-starter</artifactId> |
| 68 | <version>2.1.4</version> | 68 | <version>2.1.4</version> |
| 69 | </dependency> | 69 | </dependency> |
| 70 | + <dependency> | ||
| 71 | + <groupId>org.springframework.boot</groupId> | ||
| 72 | + <artifactId>spring-boot-starter-security</artifactId> | ||
| 73 | + </dependency> | ||
| 70 | 74 | ||
| 71 | <!-- druid数据库连接池 --> | 75 | <!-- druid数据库连接池 --> |
| 72 | <dependency> | 76 | <dependency> |
src/main/java/com/genersoft/iot/vmp/conf/security/AnonymousAuthenticationEntryPoint.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.security; | ||
| 2 | + | ||
| 3 | +import com.alibaba.fastjson.JSONObject; | ||
| 4 | +import org.slf4j.Logger; | ||
| 5 | +import org.slf4j.LoggerFactory; | ||
| 6 | +import org.springframework.security.core.AuthenticationException; | ||
| 7 | +import org.springframework.security.web.AuthenticationEntryPoint; | ||
| 8 | +import org.springframework.stereotype.Component; | ||
| 9 | + | ||
| 10 | +import javax.servlet.ServletException; | ||
| 11 | +import javax.servlet.http.HttpServletRequest; | ||
| 12 | +import javax.servlet.http.HttpServletResponse; | ||
| 13 | +import java.io.IOException; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * 处理匿名用户访问逻辑 | ||
| 17 | + */ | ||
| 18 | +@Component | ||
| 19 | +public class AnonymousAuthenticationEntryPoint implements AuthenticationEntryPoint { | ||
| 20 | + | ||
| 21 | + private final static Logger logger = LoggerFactory.getLogger(DefaultUserDetailsServiceImpl.class); | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) { | ||
| 25 | + logger.debug("用户需要登录,访问[{}]失败,AuthenticationException=[{}]", request.getRequestURI(), e.getMessage()); | ||
| 26 | + // 允许跨域 | ||
| 27 | + response.setHeader("Access-Control-Allow-Origin", "*"); | ||
| 28 | + // 允许自定义请求头token(允许head跨域) | ||
| 29 | + response.setHeader("Access-Control-Allow-Headers", "token, Accept, Origin, X-Requested-With, Content-Type, Last-Modified"); | ||
| 30 | + response.setHeader("Content-type", "application/json;charset=UTF-8"); | ||
| 31 | + JSONObject jsonObject = new JSONObject(); | ||
| 32 | + jsonObject.put("msg", e.getMessage()); | ||
| 33 | + jsonObject.put("code", "-1"); | ||
| 34 | + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); | ||
| 35 | + try { | ||
| 36 | + response.getWriter().print(jsonObject.toJSONString()); | ||
| 37 | + } catch (IOException ioException) { | ||
| 38 | + ioException.printStackTrace(); | ||
| 39 | + } | ||
| 40 | + } | ||
| 41 | +} |
src/main/java/com/genersoft/iot/vmp/conf/security/DefaultUserDetailsServiceImpl.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.security; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.conf.security.dto.LoginUser; | ||
| 4 | +import com.genersoft.iot.vmp.service.IUserService; | ||
| 5 | +import com.genersoft.iot.vmp.storager.dao.dto.User; | ||
| 6 | +import com.github.xiaoymin.knife4j.core.util.StrUtil; | ||
| 7 | +import org.slf4j.Logger; | ||
| 8 | +import org.slf4j.LoggerFactory; | ||
| 9 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 10 | +import org.springframework.security.core.CredentialsContainer; | ||
| 11 | +import org.springframework.security.core.GrantedAuthority; | ||
| 12 | +import org.springframework.security.core.SpringSecurityCoreVersion; | ||
| 13 | +import org.springframework.security.core.userdetails.UserDetails; | ||
| 14 | +import org.springframework.security.core.userdetails.UserDetailsService; | ||
| 15 | +import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||
| 16 | +import org.springframework.stereotype.Component; | ||
| 17 | +import org.springframework.stereotype.Service; | ||
| 18 | + | ||
| 19 | +import java.time.LocalDateTime; | ||
| 20 | +import java.util.Collection; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * 用户登录认证逻辑 | ||
| 24 | + */ | ||
| 25 | +@Component | ||
| 26 | +public class DefaultUserDetailsServiceImpl implements UserDetailsService { | ||
| 27 | + | ||
| 28 | + private final static Logger logger = LoggerFactory.getLogger(DefaultUserDetailsServiceImpl.class); | ||
| 29 | + | ||
| 30 | + @Autowired | ||
| 31 | + private IUserService userService; | ||
| 32 | + | ||
| 33 | + @Override | ||
| 34 | + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { | ||
| 35 | + if (StrUtil.isBlank(username)) { | ||
| 36 | + logger.info("登录用户:{} 不存在", username); | ||
| 37 | + throw new UsernameNotFoundException("登录用户:" + username + " 不存在"); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + // 查出密码 | ||
| 41 | + User user = userService.getUserByUsername(username); | ||
| 42 | + String password = SecurityUtils.encryptPassword(user.getPassword()); | ||
| 43 | + user.setPassword(password); | ||
| 44 | + if (user == null) { | ||
| 45 | + logger.info("登录用户:{} 不存在", username); | ||
| 46 | + throw new UsernameNotFoundException("登录用户:" + username + " 不存在"); | ||
| 47 | + } | ||
| 48 | + return new LoginUser(user, LocalDateTime.now()); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + | ||
| 52 | +} |
src/main/java/com/genersoft/iot/vmp/conf/security/InvalidSessionHandler.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.security; | ||
| 2 | + | ||
| 3 | +import org.slf4j.Logger; | ||
| 4 | +import org.slf4j.LoggerFactory; | ||
| 5 | +import org.springframework.security.web.session.InvalidSessionStrategy; | ||
| 6 | + | ||
| 7 | +import javax.servlet.ServletException; | ||
| 8 | +import javax.servlet.http.HttpServletRequest; | ||
| 9 | +import javax.servlet.http.HttpServletResponse; | ||
| 10 | +import java.io.IOException; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 登录超时的处理 | ||
| 14 | + */ | ||
| 15 | +public class InvalidSessionHandler implements InvalidSessionStrategy { | ||
| 16 | + | ||
| 17 | + private final static Logger logger = LoggerFactory.getLogger(InvalidSessionHandler.class); | ||
| 18 | + | ||
| 19 | + @Override | ||
| 20 | + public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse httpServletResponse) throws IOException, ServletException { | ||
| 21 | + String username = request.getParameter("username"); | ||
| 22 | + logger.info("[登录超时] - [{}]", username); | ||
| 23 | + } | ||
| 24 | +} |
src/main/java/com/genersoft/iot/vmp/conf/security/LoginFailureHandler.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.security; | ||
| 2 | + | ||
| 3 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 4 | +import org.slf4j.Logger; | ||
| 5 | +import org.slf4j.LoggerFactory; | ||
| 6 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 7 | +import org.springframework.security.authentication.*; | ||
| 8 | +import org.springframework.security.core.AuthenticationException; | ||
| 9 | +import org.springframework.security.web.authentication.AuthenticationFailureHandler; | ||
| 10 | +import org.springframework.stereotype.Component; | ||
| 11 | + | ||
| 12 | +import javax.servlet.ServletException; | ||
| 13 | +import javax.servlet.http.HttpServletRequest; | ||
| 14 | +import javax.servlet.http.HttpServletResponse; | ||
| 15 | +import java.io.IOException; | ||
| 16 | +import java.util.HashMap; | ||
| 17 | +import java.util.Map; | ||
| 18 | + | ||
| 19 | +@Component | ||
| 20 | +public class LoginFailureHandler implements AuthenticationFailureHandler { | ||
| 21 | + | ||
| 22 | + private final static Logger logger = LoggerFactory.getLogger(LoginFailureHandler.class); | ||
| 23 | + | ||
| 24 | + @Autowired | ||
| 25 | + private ObjectMapper objectMapper; | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { | ||
| 29 | + | ||
| 30 | + String username = request.getParameter("username"); | ||
| 31 | + if (e instanceof AccountExpiredException) { | ||
| 32 | + // 账号过期 | ||
| 33 | + logger.info("[登录失败] - 用户[{}]账号过期", username); | ||
| 34 | + | ||
| 35 | + } else if (e instanceof BadCredentialsException) { | ||
| 36 | + // 密码错误 | ||
| 37 | + logger.info("[登录失败] - 用户[{}]密码错误", username); | ||
| 38 | + | ||
| 39 | + } else if (e instanceof CredentialsExpiredException) { | ||
| 40 | + // 密码过期 | ||
| 41 | + logger.info("[登录失败] - 用户[{}]密码过期", username); | ||
| 42 | + | ||
| 43 | + } else if (e instanceof DisabledException) { | ||
| 44 | + // 用户被禁用 | ||
| 45 | + logger.info("[登录失败] - 用户[{}]被禁用", username); | ||
| 46 | + | ||
| 47 | + } else if (e instanceof LockedException) { | ||
| 48 | + // 用户被锁定 | ||
| 49 | + logger.info("[登录失败] - 用户[{}]被锁定", username); | ||
| 50 | + | ||
| 51 | + } else if (e instanceof InternalAuthenticationServiceException) { | ||
| 52 | + // 内部错误 | ||
| 53 | + logger.error(String.format("[登录失败] - [%s]内部错误", username), e); | ||
| 54 | + | ||
| 55 | + } else { | ||
| 56 | + // 其他错误 | ||
| 57 | + logger.error(String.format("[登录失败] - [%s]其他错误", username), e); | ||
| 58 | + } | ||
| 59 | + Map<String, Object> map = new HashMap<>(); | ||
| 60 | + map.put("code","0"); | ||
| 61 | + map.put("msg","登录失败"); | ||
| 62 | + response.setContentType("application/json;charset=UTF-8"); | ||
| 63 | + response.getWriter().write(objectMapper.writeValueAsString(map)); | ||
| 64 | + } | ||
| 65 | +} |
src/main/java/com/genersoft/iot/vmp/conf/security/LoginSuccessHandler.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.security; | ||
| 2 | + | ||
| 3 | +import org.slf4j.Logger; | ||
| 4 | +import org.slf4j.LoggerFactory; | ||
| 5 | +import org.springframework.security.core.Authentication; | ||
| 6 | +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | ||
| 7 | +import org.springframework.stereotype.Component; | ||
| 8 | + | ||
| 9 | +import javax.servlet.ServletException; | ||
| 10 | +import javax.servlet.http.HttpServletRequest; | ||
| 11 | +import javax.servlet.http.HttpServletResponse; | ||
| 12 | +import java.io.IOException; | ||
| 13 | + | ||
| 14 | +@Component | ||
| 15 | +public class LoginSuccessHandler implements AuthenticationSuccessHandler { | ||
| 16 | + | ||
| 17 | + private final static Logger logger = LoggerFactory.getLogger(LoginSuccessHandler.class); | ||
| 18 | + | ||
| 19 | + @Override | ||
| 20 | + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { | ||
| 21 | + String username = request.getParameter("username"); | ||
| 22 | + logger.info("[登录成功] - [{}]", username); | ||
| 23 | + } | ||
| 24 | +} |
src/main/java/com/genersoft/iot/vmp/conf/security/LogoutHandler.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.security; | ||
| 2 | + | ||
| 3 | +import org.slf4j.Logger; | ||
| 4 | +import org.slf4j.LoggerFactory; | ||
| 5 | +import org.springframework.security.core.Authentication; | ||
| 6 | +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; | ||
| 7 | +import org.springframework.stereotype.Component; | ||
| 8 | + | ||
| 9 | +import javax.servlet.ServletException; | ||
| 10 | +import javax.servlet.http.HttpServletRequest; | ||
| 11 | +import javax.servlet.http.HttpServletResponse; | ||
| 12 | +import java.io.IOException; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * 退出登录成功 | ||
| 16 | + */ | ||
| 17 | +@Component | ||
| 18 | +public class LogoutHandler implements LogoutSuccessHandler { | ||
| 19 | + | ||
| 20 | + private final static Logger logger = LoggerFactory.getLogger(LogoutHandler.class); | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { | ||
| 24 | + String username = request.getParameter("username"); | ||
| 25 | + logger.info("[退出登录成功] - [{}]", username); | ||
| 26 | + } | ||
| 27 | +} |
src/main/java/com/genersoft/iot/vmp/conf/security/SecurityUtils.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.security; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.conf.security.dto.LoginUser; | ||
| 4 | +import com.genersoft.iot.vmp.storager.dao.dto.User; | ||
| 5 | +import gov.nist.javax.sip.address.UserInfo; | ||
| 6 | +import org.springframework.security.authentication.AuthenticationManager; | ||
| 7 | +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
| 8 | +import org.springframework.security.core.Authentication; | ||
| 9 | +import org.springframework.security.core.context.SecurityContext; | ||
| 10 | +import org.springframework.security.core.context.SecurityContextHolder; | ||
| 11 | +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||
| 12 | + | ||
| 13 | +import javax.security.sasl.AuthenticationException; | ||
| 14 | + | ||
| 15 | +public class SecurityUtils { | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * 描述根据账号密码进行调用security进行认证授权 主动调 | ||
| 19 | + * 用AuthenticationManager的authenticate方法实现 | ||
| 20 | + * 授权成功后将用户信息存入SecurityContext当中 | ||
| 21 | + * @param username 用户名 | ||
| 22 | + * @param password 密码 | ||
| 23 | + * @param authenticationManager 认证授权管理器, | ||
| 24 | + * @see AuthenticationManager | ||
| 25 | + * @return UserInfo 用户信息 | ||
| 26 | + */ | ||
| 27 | + public static LoginUser login(String username, String password, AuthenticationManager authenticationManager) throws AuthenticationException { | ||
| 28 | + //使用security框架自带的验证token生成器 也可以自定义。 | ||
| 29 | + UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username,password); | ||
| 30 | + Authentication authenticate = authenticationManager.authenticate(token); | ||
| 31 | + SecurityContextHolder.getContext().setAuthentication(authenticate); | ||
| 32 | + LoginUser user = (LoginUser) authenticate.getPrincipal(); | ||
| 33 | + return user; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 获取当前登录的所有认证信息 | ||
| 38 | + * @return | ||
| 39 | + */ | ||
| 40 | + public static Authentication getAuthentication(){ | ||
| 41 | + SecurityContext context = SecurityContextHolder.getContext(); | ||
| 42 | + return context.getAuthentication(); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * 获取当前登录用户信息 | ||
| 47 | + * @return | ||
| 48 | + */ | ||
| 49 | + public static LoginUser getUserInfo(){ | ||
| 50 | + Authentication authentication = getAuthentication(); | ||
| 51 | + if(authentication!=null){ | ||
| 52 | + Object principal = authentication.getPrincipal(); | ||
| 53 | + if(principal!=null){ | ||
| 54 | + LoginUser user = (LoginUser) authentication.getPrincipal(); | ||
| 55 | + return user; | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | + return null; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + /** | ||
| 62 | + * 获取当前登录用户ID | ||
| 63 | + * @return | ||
| 64 | + */ | ||
| 65 | + public static int getUserId(){ | ||
| 66 | + LoginUser user = getUserInfo(); | ||
| 67 | + return user.getId(); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * 生成BCryptPasswordEncoder密码 | ||
| 72 | + * | ||
| 73 | + * @param password 密码 | ||
| 74 | + * @return 加密字符串 | ||
| 75 | + */ | ||
| 76 | + public static String encryptPassword(String password) { | ||
| 77 | + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); | ||
| 78 | + return passwordEncoder.encode(password); | ||
| 79 | + } | ||
| 80 | +} |
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.security; | ||
| 2 | + | ||
| 3 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 4 | +import org.springframework.context.annotation.Bean; | ||
| 5 | +import org.springframework.context.annotation.Configuration; | ||
| 6 | +import org.springframework.security.authentication.AuthenticationManager; | ||
| 7 | +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; | ||
| 8 | +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; | ||
| 9 | +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; | ||
| 10 | +import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
| 11 | +import org.springframework.security.config.annotation.web.builders.WebSecurity; | ||
| 12 | +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | ||
| 13 | +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | ||
| 14 | +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * 配置Spring Security | ||
| 18 | + */ | ||
| 19 | +@Configuration | ||
| 20 | +@EnableWebSecurity | ||
| 21 | +@EnableGlobalMethodSecurity(prePostEnabled = true) | ||
| 22 | +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | ||
| 23 | + | ||
| 24 | + @Autowired | ||
| 25 | + private DefaultUserDetailsServiceImpl userDetailsService; | ||
| 26 | + /** | ||
| 27 | + * 登出成功的处理 | ||
| 28 | + */ | ||
| 29 | + @Autowired | ||
| 30 | + private LoginFailureHandler loginFailureHandler; | ||
| 31 | + /** | ||
| 32 | + * 登录成功的处理 | ||
| 33 | + */ | ||
| 34 | + @Autowired | ||
| 35 | + private LoginSuccessHandler loginSuccessHandler; | ||
| 36 | + /** | ||
| 37 | + * 登出成功的处理 | ||
| 38 | + */ | ||
| 39 | + @Autowired | ||
| 40 | + private LogoutHandler logoutHandler; | ||
| 41 | + /** | ||
| 42 | + * 未登录的处理 | ||
| 43 | + */ | ||
| 44 | + @Autowired | ||
| 45 | + private AnonymousAuthenticationEntryPoint anonymousAuthenticationEntryPoint; | ||
| 46 | +// /** | ||
| 47 | +// * 超时处理 | ||
| 48 | +// */ | ||
| 49 | +// @Autowired | ||
| 50 | +// private InvalidSessionHandler invalidSessionHandler; | ||
| 51 | + | ||
| 52 | +// /** | ||
| 53 | +// * 顶号处理 | ||
| 54 | +// */ | ||
| 55 | +// @Autowired | ||
| 56 | +// private SessionInformationExpiredHandler sessionInformationExpiredHandler; | ||
| 57 | +// /** | ||
| 58 | +// * 登录用户没有权限访问资源 | ||
| 59 | +// */ | ||
| 60 | +// @Autowired | ||
| 61 | +// private LoginUserAccessDeniedHandler accessDeniedHandler; | ||
| 62 | + | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 描述: 静态资源放行,这里的放行,是不走 Spring Security 过滤器链 | ||
| 66 | + **/ | ||
| 67 | + @Override | ||
| 68 | + public void configure(WebSecurity web) { | ||
| 69 | + // 可以直接访问的静态数据 | ||
| 70 | + web.ignoring() | ||
| 71 | + .antMatchers("/") | ||
| 72 | + .antMatchers("/css/**") | ||
| 73 | + .antMatchers("/img/**") | ||
| 74 | + .antMatchers("/fonts/**") | ||
| 75 | + .antMatchers("/index.html") | ||
| 76 | + .antMatchers("/doc.html") // "/webjars/**", "/swagger-resources/**", "/v3/api-docs/**" | ||
| 77 | + .antMatchers("/webjars/**") | ||
| 78 | + .antMatchers("/swagger-resources/**") | ||
| 79 | + .antMatchers("/v3/api-docs/**") | ||
| 80 | + .antMatchers("/js/**"); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + /** | ||
| 84 | + * 配置认证方式 | ||
| 85 | + * @param auth | ||
| 86 | + * @throws Exception | ||
| 87 | + */ | ||
| 88 | + @Override | ||
| 89 | + protected void configure(AuthenticationManagerBuilder auth) throws Exception { | ||
| 90 | + DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); | ||
| 91 | + // 设置不隐藏 未找到用户异常 | ||
| 92 | + provider.setHideUserNotFoundExceptions(true); | ||
| 93 | + // 用户认证service - 查询数据库的逻辑 | ||
| 94 | + provider.setUserDetailsService(userDetailsService); | ||
| 95 | + // 设置密码加密算法 | ||
| 96 | + provider.setPasswordEncoder(passwordEncoder()); | ||
| 97 | + auth.authenticationProvider(provider); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + @Override | ||
| 101 | + protected void configure(HttpSecurity http) throws Exception { | ||
| 102 | + http.cors().and().csrf().disable(); | ||
| 103 | + http.authorizeRequests() | ||
| 104 | + // 放行接口 | ||
| 105 | + .antMatchers("/api/user/login","/index/hook/**").permitAll() | ||
| 106 | + // 除上面外的所有请求全部需要鉴权认证 | ||
| 107 | + .anyRequest().authenticated() | ||
| 108 | + // 异常处理(权限拒绝、登录失效等) | ||
| 109 | + .and().exceptionHandling() | ||
| 110 | + .authenticationEntryPoint(anonymousAuthenticationEntryPoint)//匿名用户访问无权限资源时的异常处理 | ||
| 111 | +// .accessDeniedHandler(accessDeniedHandler)//登录用户没有权限访问资源 | ||
| 112 | + // 登入 | ||
| 113 | + .and().formLogin().permitAll()//允许所有用户 | ||
| 114 | + .successHandler(loginSuccessHandler)//登录成功处理逻辑 | ||
| 115 | + .failureHandler(loginFailureHandler)//登录失败处理逻辑 | ||
| 116 | + // 登出 | ||
| 117 | + .and().logout().logoutUrl("/api/user/logout").permitAll()//允许所有用户 | ||
| 118 | + .logoutSuccessHandler(logoutHandler)//登出成功处理逻辑 | ||
| 119 | + .deleteCookies("JSESSIONID") | ||
| 120 | + // 会话管理 | ||
| 121 | +// .and().sessionManagement().invalidSessionStrategy(invalidSessionHandler) // 超时处理 | ||
| 122 | +// .maximumSessions(1)//同一账号同时登录最大用户数 | ||
| 123 | +// .expiredSessionStrategy(sessionInformationExpiredHandler) // 顶号处理 | ||
| 124 | + ; | ||
| 125 | + | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + /** | ||
| 129 | + * 描述: 密码加密算法 BCrypt 推荐使用 | ||
| 130 | + **/ | ||
| 131 | + @Bean | ||
| 132 | + public BCryptPasswordEncoder passwordEncoder() { | ||
| 133 | + return new BCryptPasswordEncoder(); | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + /** | ||
| 137 | + * 描述: 注入AuthenticationManager管理器 | ||
| 138 | + **/ | ||
| 139 | + @Override | ||
| 140 | + @Bean | ||
| 141 | + public AuthenticationManager authenticationManager() throws Exception { | ||
| 142 | + return super.authenticationManager(); | ||
| 143 | + } | ||
| 144 | +} |
src/main/java/com/genersoft/iot/vmp/conf/security/dto/LoginUser.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.security.dto; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.storager.dao.dto.User; | ||
| 4 | +import org.springframework.security.core.CredentialsContainer; | ||
| 5 | +import org.springframework.security.core.GrantedAuthority; | ||
| 6 | +import org.springframework.security.core.SpringSecurityCoreVersion; | ||
| 7 | +import org.springframework.security.core.userdetails.UserDetails; | ||
| 8 | + | ||
| 9 | +import java.time.LocalDateTime; | ||
| 10 | +import java.util.Collection; | ||
| 11 | + | ||
| 12 | +public class LoginUser implements UserDetails, CredentialsContainer { | ||
| 13 | + | ||
| 14 | + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; | ||
| 15 | + | ||
| 16 | + /** | ||
| 17 | + * 用户 | ||
| 18 | + */ | ||
| 19 | + private User user; | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 登录时间 | ||
| 24 | + */ | ||
| 25 | + private LocalDateTime loginTime; | ||
| 26 | + | ||
| 27 | + public LoginUser(User user, LocalDateTime loginTime) { | ||
| 28 | + this.user = user; | ||
| 29 | + this.loginTime = loginTime; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + @Override | ||
| 34 | + public Collection<? extends GrantedAuthority> getAuthorities() { | ||
| 35 | + return null; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @Override | ||
| 39 | + public String getPassword() { | ||
| 40 | + return user.getPassword(); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + @Override | ||
| 44 | + public String getUsername() { | ||
| 45 | + return user.getUsername(); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * 账户是否未过期,过期无法验证 | ||
| 50 | + */ | ||
| 51 | + @Override | ||
| 52 | + public boolean isAccountNonExpired() { | ||
| 53 | + return true; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * 指定用户是否解锁,锁定的用户无法进行身份验证 | ||
| 58 | + * <p> | ||
| 59 | + * 密码锁定 | ||
| 60 | + * </p> | ||
| 61 | + */ | ||
| 62 | + @Override | ||
| 63 | + public boolean isAccountNonLocked() { | ||
| 64 | + return true; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证 | ||
| 69 | + */ | ||
| 70 | + @Override | ||
| 71 | + public boolean isCredentialsNonExpired() { | ||
| 72 | + return true; | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + /** | ||
| 76 | + * 用户是否被启用或禁用。禁用的用户无法进行身份验证。 | ||
| 77 | + */ | ||
| 78 | + @Override | ||
| 79 | + public boolean isEnabled() { | ||
| 80 | + return true; | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + /** | ||
| 84 | + * 认证完成后,擦除密码 | ||
| 85 | + */ | ||
| 86 | + @Override | ||
| 87 | + public void eraseCredentials() { | ||
| 88 | + user.setPassword(null); | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + | ||
| 92 | + public int getId() { | ||
| 93 | + return user.getId(); | ||
| 94 | + } | ||
| 95 | +} |
src/main/java/com/genersoft/iot/vmp/service/IUserService.java
src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java
| @@ -24,4 +24,9 @@ public class UserServiceImpl implements IUserService { | @@ -24,4 +24,9 @@ public class UserServiceImpl implements IUserService { | ||
| 24 | user.setPassword(password); | 24 | user.setPassword(password); |
| 25 | return userMapper.update(user) > 0; | 25 | return userMapper.update(user) > 0; |
| 26 | } | 26 | } |
| 27 | + | ||
| 28 | + @Override | ||
| 29 | + public User getUserByUsername(String username) { | ||
| 30 | + return userMapper.getUserByUsername(username); | ||
| 31 | + } | ||
| 27 | } | 32 | } |
src/main/java/com/genersoft/iot/vmp/storager/dao/UserMapper.java
| @@ -28,4 +28,7 @@ public interface UserMapper { | @@ -28,4 +28,7 @@ public interface UserMapper { | ||
| 28 | 28 | ||
| 29 | @Select("select * FROM user WHERE id= #{id}") | 29 | @Select("select * FROM user WHERE id= #{id}") |
| 30 | User selectById(int id); | 30 | User selectById(int id); |
| 31 | + | ||
| 32 | + @Select("select * FROM user WHERE username= #{username}") | ||
| 33 | + User getUserByUsername(String username); | ||
| 31 | } | 34 | } |
src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
| 1 | package com.genersoft.iot.vmp.vmanager.user; | 1 | package com.genersoft.iot.vmp.vmanager.user; |
| 2 | 2 | ||
| 3 | +import com.genersoft.iot.vmp.conf.security.SecurityUtils; | ||
| 4 | +import com.genersoft.iot.vmp.conf.security.dto.LoginUser; | ||
| 3 | import com.genersoft.iot.vmp.service.IUserService; | 5 | import com.genersoft.iot.vmp.service.IUserService; |
| 4 | import com.genersoft.iot.vmp.storager.dao.dto.User; | 6 | import com.genersoft.iot.vmp.storager.dao.dto.User; |
| 5 | import io.swagger.annotations.Api; | 7 | import io.swagger.annotations.Api; |
| @@ -8,11 +10,12 @@ import io.swagger.annotations.ApiImplicitParams; | @@ -8,11 +10,12 @@ import io.swagger.annotations.ApiImplicitParams; | ||
| 8 | import io.swagger.annotations.ApiOperation; | 10 | import io.swagger.annotations.ApiOperation; |
| 9 | import org.springframework.beans.factory.annotation.Autowired; | 11 | import org.springframework.beans.factory.annotation.Autowired; |
| 10 | import org.springframework.beans.factory.annotation.Value; | 12 | import org.springframework.beans.factory.annotation.Value; |
| 13 | +import org.springframework.security.authentication.AuthenticationManager; | ||
| 14 | +import org.springframework.util.DigestUtils; | ||
| 11 | import org.springframework.util.StringUtils; | 15 | import org.springframework.util.StringUtils; |
| 12 | -import org.springframework.web.bind.annotation.CrossOrigin; | ||
| 13 | -import org.springframework.web.bind.annotation.GetMapping; | ||
| 14 | -import org.springframework.web.bind.annotation.RequestMapping; | ||
| 15 | -import org.springframework.web.bind.annotation.RestController; | 16 | +import org.springframework.web.bind.annotation.*; |
| 17 | + | ||
| 18 | +import javax.security.sasl.AuthenticationException; | ||
| 16 | 19 | ||
| 17 | @Api(tags = "用户管理") | 20 | @Api(tags = "用户管理") |
| 18 | @CrossOrigin | 21 | @CrossOrigin |
| @@ -21,21 +24,46 @@ import org.springframework.web.bind.annotation.RestController; | @@ -21,21 +24,46 @@ import org.springframework.web.bind.annotation.RestController; | ||
| 21 | public class UserController { | 24 | public class UserController { |
| 22 | 25 | ||
| 23 | @Autowired | 26 | @Autowired |
| 24 | - private IUserService userService; | 27 | + AuthenticationManager authenticationManager; |
| 25 | 28 | ||
| 29 | + @Autowired | ||
| 30 | + IUserService userService; | ||
| 26 | 31 | ||
| 27 | @ApiOperation("登录") | 32 | @ApiOperation("登录") |
| 28 | @ApiImplicitParams({ | 33 | @ApiImplicitParams({ |
| 29 | @ApiImplicitParam(name = "username", value = "用户名", dataTypeClass = String.class), | 34 | @ApiImplicitParam(name = "username", value = "用户名", dataTypeClass = String.class), |
| 30 | - @ApiImplicitParam(name = "password", value = "密码(32未md5加密)", dataTypeClass = String.class), | 35 | + @ApiImplicitParam(name = "password", value = "密码(32位md5加密)", dataTypeClass = String.class), |
| 31 | }) | 36 | }) |
| 32 | @GetMapping("/login") | 37 | @GetMapping("/login") |
| 33 | public String login(String username, String password){ | 38 | public String login(String username, String password){ |
| 34 | - User user = userService.getUser(username, password); | 39 | + LoginUser user = null; |
| 40 | + try { | ||
| 41 | + user = SecurityUtils.login(username, password, authenticationManager); | ||
| 42 | + } catch (AuthenticationException e) { | ||
| 43 | + e.printStackTrace(); | ||
| 44 | + return "fail"; | ||
| 45 | + } | ||
| 35 | if (user != null) { | 46 | if (user != null) { |
| 36 | return "success"; | 47 | return "success"; |
| 37 | }else { | 48 | }else { |
| 38 | return "fail"; | 49 | return "fail"; |
| 39 | } | 50 | } |
| 40 | } | 51 | } |
| 52 | + | ||
| 53 | + @ApiOperation("修改密码") | ||
| 54 | + @ApiImplicitParams({ | ||
| 55 | + @ApiImplicitParam(name = "username", value = "用户名", dataTypeClass = String.class), | ||
| 56 | + @ApiImplicitParam(name = "password", value = "密码(未md5加密的密码)", dataTypeClass = String.class), | ||
| 57 | + }) | ||
| 58 | + @PostMapping("/changePassword") | ||
| 59 | + public String changePassword(String password){ | ||
| 60 | + // 获取当前登录用户id | ||
| 61 | + int userId = SecurityUtils.getUserId(); | ||
| 62 | + boolean result = userService.changePassword(userId, DigestUtils.md5DigestAsHex(password.getBytes())); | ||
| 63 | + if (result) { | ||
| 64 | + return "success"; | ||
| 65 | + }else { | ||
| 66 | + return "fail"; | ||
| 67 | + } | ||
| 68 | + } | ||
| 41 | } | 69 | } |
web_src/config/index.js
web_src/src/components/DeviceList.vue
| @@ -215,8 +215,8 @@ | @@ -215,8 +215,8 @@ | ||
| 215 | console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `); | 215 | console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `); |
| 216 | let that = this; | 216 | let that = this; |
| 217 | this.$axios({ | 217 | this.$axios({ |
| 218 | - method: 'get', | ||
| 219 | - url: '/api/device/query/transport' + row.deviceId + '/' + row.streamMode | 218 | + method: 'post', |
| 219 | + url: '/api/device/query/transport/' + row.deviceId + '/' + row.streamMode | ||
| 220 | }).then(function(res) { | 220 | }).then(function(res) { |
| 221 | 221 | ||
| 222 | }).catch(function(e) { | 222 | }).catch(function(e) { |
web_src/src/components/Login.vue
| @@ -63,7 +63,7 @@ export default { | @@ -63,7 +63,7 @@ export default { | ||
| 63 | 63 | ||
| 64 | this.$axios({ | 64 | this.$axios({ |
| 65 | method: 'get', | 65 | method: 'get', |
| 66 | - url:"/api/user/login", | 66 | + url:"/api/user/login", |
| 67 | params: loginParam | 67 | params: loginParam |
| 68 | }).then(function (res) { | 68 | }).then(function (res) { |
| 69 | console.log(JSON.stringify(res)); | 69 | console.log(JSON.stringify(res)); |
| @@ -81,7 +81,7 @@ export default { | @@ -81,7 +81,7 @@ export default { | ||
| 81 | }); | 81 | }); |
| 82 | } | 82 | } |
| 83 | }).catch(function (error) { | 83 | }).catch(function (error) { |
| 84 | - that.$message.error(error.response.statusText); | 84 | + that.$message.error(error.response.data.msg); |
| 85 | that.isLoging = false; | 85 | that.isLoging = false; |
| 86 | }); | 86 | }); |
| 87 | }, | 87 | }, |
web_src/src/components/UiHeader.vue
| 1 | <template> | 1 | <template> |
| 2 | <div id="UiHeader"> | 2 | <div id="UiHeader"> |
| 3 | - <el-menu router :default-active="this.$route.path" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" mode="horizontal"> | 3 | + <el-menu router :default-active="this.$route.path" menu-trigger="click" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" mode="horizontal"> |
| 4 | <el-menu-item index="/">控制台</el-menu-item> | 4 | <el-menu-item index="/">控制台</el-menu-item> |
| 5 | <el-menu-item index="/deviceList">设备列表</el-menu-item> | 5 | <el-menu-item index="/deviceList">设备列表</el-menu-item> |
| 6 | <el-menu-item index="/pushVideoList">推流列表</el-menu-item> | 6 | <el-menu-item index="/pushVideoList">推流列表</el-menu-item> |
| 7 | <el-menu-item index="/streamProxyList">拉流代理</el-menu-item> | 7 | <el-menu-item index="/streamProxyList">拉流代理</el-menu-item> |
| 8 | <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item> | 8 | <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item> |
| 9 | + <el-menu-item @click="openDoc">在线文档</el-menu-item> | ||
| 9 | <el-switch v-model="alarmNotify" active-text="报警信息推送" style="display: block float: right" @change="sseControl"></el-switch> | 10 | <el-switch v-model="alarmNotify" active-text="报警信息推送" style="display: block float: right" @change="sseControl"></el-switch> |
| 10 | - <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item> | 11 | +<!-- <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>--> |
| 12 | + <el-submenu index="" style="float: right;" > | ||
| 13 | + <template slot="title">欢迎,{{this.$cookies.get("session").username}}</template> | ||
| 14 | + <el-menu-item @click="changePassword">修改密码</el-menu-item> | ||
| 15 | + <el-menu-item @click="loginout">注销</el-menu-item> | ||
| 16 | + </el-submenu> | ||
| 11 | </el-menu> | 17 | </el-menu> |
| 18 | + <changePasswordDialog ref="changePasswordDialog"></changePasswordDialog> | ||
| 12 | </div> | 19 | </div> |
| 13 | </template> | 20 | </template> |
| 14 | 21 | ||
| 15 | <script> | 22 | <script> |
| 23 | + | ||
| 24 | +import changePasswordDialog from './dialog/changePassword.vue' | ||
| 16 | export default { | 25 | export default { |
| 17 | name: "UiHeader", | 26 | name: "UiHeader", |
| 18 | - components: { Notification }, | 27 | + components: { Notification, changePasswordDialog }, |
| 19 | data() { | 28 | data() { |
| 20 | return { | 29 | return { |
| 21 | alarmNotify: true, | 30 | alarmNotify: true, |
| @@ -24,10 +33,25 @@ export default { | @@ -24,10 +33,25 @@ export default { | ||
| 24 | }, | 33 | }, |
| 25 | methods:{ | 34 | methods:{ |
| 26 | loginout(){ | 35 | loginout(){ |
| 36 | + this.$axios({ | ||
| 37 | + method: 'get', | ||
| 38 | + url:"/api/user/logout" | ||
| 39 | + }).then((res)=> { | ||
| 27 | // 删除cookie,回到登录页面 | 40 | // 删除cookie,回到登录页面 |
| 28 | this.$cookies.remove("session"); | 41 | this.$cookies.remove("session"); |
| 29 | this.$router.push('/login'); | 42 | this.$router.push('/login'); |
| 30 | this.sseSource.close(); | 43 | this.sseSource.close(); |
| 44 | + }).catch((error)=> { | ||
| 45 | + console.error("登出失败") | ||
| 46 | + console.error(error) | ||
| 47 | + }); | ||
| 48 | + }, | ||
| 49 | + changePassword(){ | ||
| 50 | + this.$refs.changePasswordDialog.openDialog() | ||
| 51 | + }, | ||
| 52 | + openDoc(){ | ||
| 53 | + console.log(process.env.BASE_API) | ||
| 54 | + window.open( !!process.env.BASE_API? process.env.BASE_API + "/doc.html": "/doc.html") | ||
| 31 | }, | 55 | }, |
| 32 | beforeunloadHandler() { | 56 | beforeunloadHandler() { |
| 33 | this.sseSource.close(); | 57 | this.sseSource.close(); |
web_src/src/components/dialog/changePassword.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div id="changePassword" v-loading="isLoging"> | ||
| 3 | + <el-dialog | ||
| 4 | + title="修改密码" | ||
| 5 | + width="40%" | ||
| 6 | + top="2rem" | ||
| 7 | + :close-on-click-modal="false" | ||
| 8 | + :visible.sync="showDialog" | ||
| 9 | + :destroy-on-close="true" | ||
| 10 | + @close="close()" | ||
| 11 | + > | ||
| 12 | + <div id="shared" style="margin-right: 20px;"> | ||
| 13 | + <el-form ref="passwordForm" :rules="rules" status-icon label-width="80px"> | ||
| 14 | + <el-form-item label="新密码" prop="newPassword" > | ||
| 15 | + <el-input v-model="newPassword" autocomplete="off"></el-input> | ||
| 16 | + </el-form-item> | ||
| 17 | + <el-form-item label="确认密码" prop="confirmPassword"> | ||
| 18 | + <el-input v-model="confirmPassword" autocomplete="off"></el-input> | ||
| 19 | + </el-form-item> | ||
| 20 | + | ||
| 21 | + <el-form-item> | ||
| 22 | + <div style="float: right;"> | ||
| 23 | + <el-button type="primary" @click="onSubmit">保存</el-button> | ||
| 24 | + <el-button @click="close">取消</el-button> | ||
| 25 | + </div> | ||
| 26 | + </el-form-item> | ||
| 27 | + </el-form> | ||
| 28 | + </div> | ||
| 29 | + </el-dialog> | ||
| 30 | + </div> | ||
| 31 | +</template> | ||
| 32 | + | ||
| 33 | +<script> | ||
| 34 | +export default { | ||
| 35 | + name: "changePassword", | ||
| 36 | + props: {}, | ||
| 37 | + computed: {}, | ||
| 38 | + created() {}, | ||
| 39 | + data() { | ||
| 40 | + let validatePass = (rule, value, callback) => { | ||
| 41 | + if (value === '') { | ||
| 42 | + callback(new Error('请输入密码')); | ||
| 43 | + } else { | ||
| 44 | + if (this.confirmPassword !== '') { | ||
| 45 | + this.$refs.passwordForm.validateField('confirmPassword'); | ||
| 46 | + } | ||
| 47 | + callback(); | ||
| 48 | + } | ||
| 49 | + }; | ||
| 50 | + let validatePass2 = (rule, value, callback) => { | ||
| 51 | + if (this.confirmPassword === '') { | ||
| 52 | + callback(new Error('请再次输入密码')); | ||
| 53 | + } else if (this.confirmPassword !== this.newPassword) { | ||
| 54 | + callback(new Error('两次输入密码不一致!')); | ||
| 55 | + } else { | ||
| 56 | + callback(); | ||
| 57 | + } | ||
| 58 | + }; | ||
| 59 | + return { | ||
| 60 | + newPassword: null, | ||
| 61 | + confirmPassword: null, | ||
| 62 | + showDialog: false, | ||
| 63 | + isLoging: false, | ||
| 64 | + rules: { | ||
| 65 | + newPassword: [{ required: true, validator: validatePass, trigger: "blur" }], | ||
| 66 | + confirmPassword: [{ required: true, validator: validatePass2, trigger: "blur" }], | ||
| 67 | + }, | ||
| 68 | + }; | ||
| 69 | + }, | ||
| 70 | + methods: { | ||
| 71 | + openDialog: function () { | ||
| 72 | + this.showDialog = true; | ||
| 73 | + }, | ||
| 74 | + onSubmit: function () { | ||
| 75 | + this.$axios({ | ||
| 76 | + method: 'post', | ||
| 77 | + url:"/api/user/changePassword", | ||
| 78 | + params: { | ||
| 79 | + password: this.newPassword | ||
| 80 | + } | ||
| 81 | + }).then((res)=> { | ||
| 82 | + if (res.data === "success"){ | ||
| 83 | + this.$message({ | ||
| 84 | + showClose: true, | ||
| 85 | + message: '修改成功,请重新登陆', | ||
| 86 | + type: 'success' | ||
| 87 | + }); | ||
| 88 | + this.showDialog = false; | ||
| 89 | + setTimeout(()=>{ | ||
| 90 | + // 删除cookie,回到登录页面 | ||
| 91 | + this.$cookies.remove("session"); | ||
| 92 | + this.$router.push('/login'); | ||
| 93 | + this.sseSource.close(); | ||
| 94 | + },800) | ||
| 95 | + } | ||
| 96 | + }).catch((error)=> { | ||
| 97 | + console.error(error) | ||
| 98 | + }); | ||
| 99 | + }, | ||
| 100 | + close: function () { | ||
| 101 | + this.showDialog = false; | ||
| 102 | + this.newPassword= null; | ||
| 103 | + this.confirmPassword=null; | ||
| 104 | + }, | ||
| 105 | + }, | ||
| 106 | +}; | ||
| 107 | +</script> |
web_src/src/main.js
| @@ -40,6 +40,18 @@ Vue.prototype.$notify = Notification; | @@ -40,6 +40,18 @@ Vue.prototype.$notify = Notification; | ||
| 40 | 40 | ||
| 41 | axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : ""; | 41 | axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : ""; |
| 42 | 42 | ||
| 43 | +// api 返回401自动回登陆页面 | ||
| 44 | +axios.interceptors.response.use(function (response) { | ||
| 45 | + // 对响应数据做点什么 | ||
| 46 | + return response; | ||
| 47 | +}, function (error) { | ||
| 48 | + // 对响应错误做点什么 | ||
| 49 | + if (error.response.status === 401) { | ||
| 50 | + router.push('/login'); | ||
| 51 | + } | ||
| 52 | + return Promise.reject(error); | ||
| 53 | +}); | ||
| 54 | + | ||
| 43 | Vue.prototype.$cookies.config(60*30); | 55 | Vue.prototype.$cookies.config(60*30); |
| 44 | 56 | ||
| 45 | 57 |