Commit cb5849d8a14f55241c44bdf6724b18de7950564d

Authored by panlinlin
1 parent 123ce171

支持接口鉴权,支持修改密码,

... ... @@ -67,6 +67,10 @@
67 67 <artifactId>mybatis-spring-boot-starter</artifactId>
68 68 <version>2.1.4</version>
69 69 </dependency>
  70 + <dependency>
  71 + <groupId>org.springframework.boot</groupId>
  72 + <artifactId>spring-boot-starter-security</artifactId>
  73 + </dependency>
70 74  
71 75 <!-- druid数据库连接池 -->
72 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
... ... @@ -8,5 +8,5 @@ public interface IUserService {
8 8  
9 9 boolean changePassword(int id, String password);
10 10  
11   -
  11 + User getUserByUsername(String username);
12 12 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java
... ... @@ -24,4 +24,9 @@ public class UserServiceImpl implements IUserService {
24 24 user.setPassword(password);
25 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 28  
29 29 @Select("select * FROM user WHERE id= #{id}")
30 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 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 5 import com.genersoft.iot.vmp.service.IUserService;
4 6 import com.genersoft.iot.vmp.storager.dao.dto.User;
5 7 import io.swagger.annotations.Api;
... ... @@ -8,11 +10,12 @@ import io.swagger.annotations.ApiImplicitParams;
8 10 import io.swagger.annotations.ApiOperation;
9 11 import org.springframework.beans.factory.annotation.Autowired;
10 12 import org.springframework.beans.factory.annotation.Value;
  13 +import org.springframework.security.authentication.AuthenticationManager;
  14 +import org.springframework.util.DigestUtils;
11 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 20 @Api(tags = "用户管理")
18 21 @CrossOrigin
... ... @@ -21,21 +24,46 @@ import org.springframework.web.bind.annotation.RestController;
21 24 public class UserController {
22 25  
23 26 @Autowired
24   - private IUserService userService;
  27 + AuthenticationManager authenticationManager;
25 28  
  29 + @Autowired
  30 + IUserService userService;
26 31  
27 32 @ApiOperation("登录")
28 33 @ApiImplicitParams({
29 34 @ApiImplicitParam(name = "username", value = "用户名", dataTypeClass = String.class),
30   - @ApiImplicitParam(name = "password", value = "密码(32md5加密)", dataTypeClass = String.class),
  35 + @ApiImplicitParam(name = "password", value = "密码(32md5加密)", dataTypeClass = String.class),
31 36 })
32 37 @GetMapping("/login")
33 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 46 if (user != null) {
36 47 return "success";
37 48 }else {
38 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
... ... @@ -17,7 +17,8 @@ module.exports = {
17 17 pathRewrite: {
18 18 '^/debug': '/'
19 19 }
20   - }
  20 + },
  21 +
21 22 },
22 23  
23 24 // Various Dev Server settings
... ...
web_src/src/components/DeviceList.vue
... ... @@ -215,8 +215,8 @@
215 215 console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `);
216 216 let that = this;
217 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 220 }).then(function(res) {
221 221  
222 222 }).catch(function(e) {
... ...
web_src/src/components/Login.vue
... ... @@ -63,7 +63,7 @@ export default {
63 63  
64 64 this.$axios({
65 65 method: 'get',
66   - url:"/api/user/login",
  66 + url:"/api/user/login",
67 67 params: loginParam
68 68 }).then(function (res) {
69 69 console.log(JSON.stringify(res));
... ... @@ -81,7 +81,7 @@ export default {
81 81 });
82 82 }
83 83 }).catch(function (error) {
84   - that.$message.error(error.response.statusText);
  84 + that.$message.error(error.response.data.msg);
85 85 that.isLoging = false;
86 86 });
87 87 },
... ...
web_src/src/components/UiHeader.vue
1 1 <template>
2 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 4 <el-menu-item index="/">控制台</el-menu-item>
5 5 <el-menu-item index="/deviceList">设备列表</el-menu-item>
6 6 <el-menu-item index="/pushVideoList">推流列表</el-menu-item>
7 7 <el-menu-item index="/streamProxyList">拉流代理</el-menu-item>
8 8 <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
  9 + <el-menu-item @click="openDoc">在线文档</el-menu-item>
9 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 17 </el-menu>
  18 + <changePasswordDialog ref="changePasswordDialog"></changePasswordDialog>
12 19 </div>
13 20 </template>
14 21  
15 22 <script>
  23 +
  24 +import changePasswordDialog from './dialog/changePassword.vue'
16 25 export default {
17 26 name: "UiHeader",
18   - components: { Notification },
  27 + components: { Notification, changePasswordDialog },
19 28 data() {
20 29 return {
21 30 alarmNotify: true,
... ... @@ -24,10 +33,25 @@ export default {
24 33 },
25 34 methods:{
26 35 loginout(){
  36 + this.$axios({
  37 + method: 'get',
  38 + url:"/api/user/logout"
  39 + }).then((res)=> {
27 40 // 删除cookie,回到登录页面
28 41 this.$cookies.remove("session");
29 42 this.$router.push('/login');
30 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 56 beforeunloadHandler() {
33 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 40  
41 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 55 Vue.prototype.$cookies.config(60*30);
44 56  
45 57  
... ...