diff --git a/mall-admin/src/main/java/com/macro/mall/component/BindingResultAspect.java b/mall-admin/src/main/java/com/macro/mall/component/BindingResultAspect.java index 3ba56d2..54fad25 100644 --- a/mall-admin/src/main/java/com/macro/mall/component/BindingResultAspect.java +++ b/mall-admin/src/main/java/com/macro/mall/component/BindingResultAspect.java @@ -27,7 +27,7 @@ public class BindingResultAspect { if (arg instanceof BindingResult) { BindingResult result = (BindingResult) arg; if (result.hasErrors()) { - return new CommonResult().validateFailed(result.getFieldError().getDefaultMessage()); + return new CommonResult().validateFailed(result); } } } diff --git a/mall-admin/src/main/java/com/macro/mall/config/SecurityConfig.java b/mall-admin/src/main/java/com/macro/mall/config/SecurityConfig.java index 4583f84..ecafd0e 100644 --- a/mall-admin/src/main/java/com/macro/mall/config/SecurityConfig.java +++ b/mall-admin/src/main/java/com/macro/mall/config/SecurityConfig.java @@ -9,6 +9,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.encoding.Md5PasswordEncoder; +import org.springframework.security.authentication.encoding.PasswordEncoder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @@ -48,7 +49,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { "/v2/api-docs/**" ) .permitAll() - .antMatchers("/auth/**")// 对于获取token的rest api要允许匿名访问 + .antMatchers("/admin/**")// 对于获取token的rest api要允许匿名访问 .permitAll() .anyRequest()// 除上面外的所有请求全部需要鉴权认证 .authenticated(); @@ -61,7 +62,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService()) - .passwordEncoder(new Md5PasswordEncoder()); + .passwordEncoder(passwordEncoder()); + } + + @Bean + public PasswordEncoder passwordEncoder(){ + return new Md5PasswordEncoder(); } @Bean diff --git a/mall-admin/src/main/java/com/macro/mall/controller/UmsAdminController.java b/mall-admin/src/main/java/com/macro/mall/controller/UmsAdminController.java new file mode 100644 index 0000000..74d6adf --- /dev/null +++ b/mall-admin/src/main/java/com/macro/mall/controller/UmsAdminController.java @@ -0,0 +1,66 @@ +package com.macro.mall.controller; + +import com.macro.mall.dto.CommonResult; +import com.macro.mall.dto.UmsAdminLoginParam; +import com.macro.mall.dto.UmsAdminParam; +import com.macro.mall.model.UmsAdmin; +import com.macro.mall.service.UmsAdminService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Controller; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; + +/** + * 后台用户管理 + */ +@Controller +@Api(tags = "UmsAdminController", description = "后台用户管理") +@RequestMapping("/admin") +public class UmsAdminController { + @Autowired + private UmsAdminService adminService; + @Value("${jwt.tokenHeader}") + private String tokenHeader; + + @ApiOperation(value = "用户注册") + @RequestMapping(value = "/register", method = RequestMethod.POST) + @ResponseBody + public Object register(@RequestBody UmsAdminParam umsAdminParam, BindingResult result) { + UmsAdmin umsAdmin = adminService.register(umsAdminParam); + if (umsAdmin == null) { + new CommonResult().failed(); + } + return new CommonResult().success(umsAdmin); + } + + @ApiOperation(value = "登录以后返回token") + @RequestMapping(value = "/login", method = RequestMethod.POST) + @ResponseBody + public Object login(@RequestBody UmsAdminLoginParam umsAdminLoginParam, BindingResult result) { + String token = adminService.login(umsAdminLoginParam.getUsername(), umsAdminLoginParam.getPassword()); + if (token == null) { + new CommonResult().failed(); + } + return new CommonResult().success(token); + } + + @ApiOperation(value = "刷新token") + @RequestMapping(value = "/token/refresh", method = RequestMethod.GET) + @ResponseBody + public Object refreshToken(HttpServletRequest request) { + String token = request.getHeader(tokenHeader); + String refreshToken = adminService.refreshToken(token); + if (refreshToken == null) { + return new CommonResult().failed(); + } + return new CommonResult().success(token); + } +} diff --git a/mall-admin/src/main/java/com/macro/mall/dto/PmsBrandParam.java b/mall-admin/src/main/java/com/macro/mall/dto/PmsBrandParam.java index 8ae06fa..6968918 100644 --- a/mall-admin/src/main/java/com/macro/mall/dto/PmsBrandParam.java +++ b/mall-admin/src/main/java/com/macro/mall/dto/PmsBrandParam.java @@ -11,7 +11,6 @@ import javax.validation.constraints.NotNull; /** * 品牌传递参数 */ -@ApiModel(value = "PmsBrandParam") public class PmsBrandParam { @ApiModelProperty(value = "品牌名称",required = true) @NotEmpty(message = "名称不能为空") diff --git a/mall-admin/src/main/java/com/macro/mall/dto/UmsAdminLoginParam.java b/mall-admin/src/main/java/com/macro/mall/dto/UmsAdminLoginParam.java new file mode 100644 index 0000000..a70ecb8 --- /dev/null +++ b/mall-admin/src/main/java/com/macro/mall/dto/UmsAdminLoginParam.java @@ -0,0 +1,32 @@ +package com.macro.mall.dto; + +import io.swagger.annotations.ApiModelProperty; +import org.hibernate.validator.constraints.NotEmpty; + +/** + * 用户登录参数 + */ +public class UmsAdminLoginParam { + @ApiModelProperty(value = "用户名", required = true) + @NotEmpty(message = "用户名不能为空") + private String username; + @ApiModelProperty(value = "密码", required = true) + @NotEmpty(message = "密码不能为空") + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/mall-admin/src/main/java/com/macro/mall/dto/UmsAdminParam.java b/mall-admin/src/main/java/com/macro/mall/dto/UmsAdminParam.java new file mode 100644 index 0000000..d35e579 --- /dev/null +++ b/mall-admin/src/main/java/com/macro/mall/dto/UmsAdminParam.java @@ -0,0 +1,54 @@ +package com.macro.mall.dto; + +import io.swagger.annotations.ApiModelProperty; +import org.hibernate.validator.constraints.Email; +import org.hibernate.validator.constraints.NotEmpty; + +/** + * 用户登录参数 + */ +public class UmsAdminParam { + @ApiModelProperty(value = "用户名", required = true) + @NotEmpty(message = "用户名不能为空") + private String username; + @ApiModelProperty(value = "密码", required = true) + @NotEmpty(message = "密码不能为空") + private String password; + @ApiModelProperty(value = "用户头像") + private String icon; + @ApiModelProperty(value = "邮箱") + @Email(message = "邮箱格式不合法") + private String email; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } +} diff --git a/mall-admin/src/main/java/com/macro/mall/service/UmsAdminService.java b/mall-admin/src/main/java/com/macro/mall/service/UmsAdminService.java index 56cf878..686bc01 100644 --- a/mall-admin/src/main/java/com/macro/mall/service/UmsAdminService.java +++ b/mall-admin/src/main/java/com/macro/mall/service/UmsAdminService.java @@ -1,5 +1,6 @@ package com.macro.mall.service; +import com.macro.mall.dto.UmsAdminParam; import com.macro.mall.model.UmsAdmin; /** @@ -10,4 +11,23 @@ public interface UmsAdminService { * 根据用户名获取后台管理员 */ UmsAdmin getAdminByUsername(String username); + + /** + * 注册功能 + */ + UmsAdmin register(UmsAdminParam umsAdminParam); + + /** + * 登录功能 + * @param username 用户名 + * @param password 密码 + * @return 生成的JWT的token + */ + String login(String username,String password); + + /** + * 刷新token的功能 + * @param oldToken 旧的token + */ + String refreshToken(String oldToken); } diff --git a/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminServiceImpl.java b/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminServiceImpl.java index 0d34b82..8b93ad7 100644 --- a/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminServiceImpl.java +++ b/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminServiceImpl.java @@ -1,10 +1,21 @@ package com.macro.mall.service.impl; +import com.macro.mall.dto.UmsAdminParam; import com.macro.mall.mapper.UmsAdminMapper; import com.macro.mall.model.UmsAdmin; import com.macro.mall.model.UmsAdminExample; import com.macro.mall.service.UmsAdminService; +import com.macro.mall.util.JwtTokenUtil; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.encoding.PasswordEncoder; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Service; import java.util.List; @@ -16,6 +27,17 @@ import java.util.List; public class UmsAdminServiceImpl implements UmsAdminService{ @Autowired private UmsAdminMapper adminMapper; + @Autowired + private AuthenticationManager authenticationManager; + @Autowired + private UserDetailsService userDetailsService; + @Autowired + private JwtTokenUtil jwtTokenUtil; + @Autowired + private PasswordEncoder passwordEncoder; + @Value("${jwt.tokenHead}") + private String tokenHead; + @Override public UmsAdmin getAdminByUsername(String username) { UmsAdminExample example = new UmsAdminExample(); @@ -26,4 +48,40 @@ public class UmsAdminServiceImpl implements UmsAdminService{ } return null; } + + @Override + public UmsAdmin register(UmsAdminParam umsAdminParam) { + UmsAdmin umsAdmin = new UmsAdmin(); + BeanUtils.copyProperties(umsAdminParam,umsAdmin); + //查询是否有相同用户名的用户 + UmsAdminExample example = new UmsAdminExample(); + example.createCriteria().andUsernameEqualTo(umsAdmin.getUsername()); + List umsAdminList = adminMapper.selectByExample(example); + if(umsAdminList.size()>0){ + return null; + } + //将密码进行加密操作 + String md5Password = passwordEncoder.encodePassword(umsAdmin.getPassword(), null); + umsAdmin.setPassword(md5Password); + adminMapper.insert(umsAdmin); + return umsAdmin; + } + + @Override + public String login(String username, String password) { + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,password); + Authentication authentication = authenticationManager.authenticate(authenticationToken); + SecurityContextHolder.getContext().setAuthentication(authentication); + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + return jwtTokenUtil.generateToken(userDetails); + } + + @Override + public String refreshToken(String oldToken) { + String token = oldToken.substring(tokenHead.length()); + if(jwtTokenUtil.canRefresh(token)){ + return jwtTokenUtil.refreshToken(token); + } + return null; + } } diff --git a/mall-admin/src/main/java/com/macro/mall/util/JwtTokenUtil.java b/mall-admin/src/main/java/com/macro/mall/util/JwtTokenUtil.java index 45f7640..14fd5a8 100644 --- a/mall-admin/src/main/java/com/macro/mall/util/JwtTokenUtil.java +++ b/mall-admin/src/main/java/com/macro/mall/util/JwtTokenUtil.java @@ -1,13 +1,14 @@ package com.macro.mall.util; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; import java.util.Date; +import java.util.HashMap; import java.util.Map; /** @@ -22,6 +23,7 @@ import java.util.Map; */ @Component public class JwtTokenUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenUtil.class); private static final String CLAIM_KEY_USERNAME = "sub"; private static final String CLAIM_KEY_CREATED = "created"; @Value("${jwt.secret}") @@ -32,26 +34,26 @@ public class JwtTokenUtil { /** * 根据负责生成JWT的token */ - String generateToken(Map claims) { + private String generateToken(Map claims) { return Jwts.builder() .setClaims(claims) .setExpiration(generateExpirationDate()) - .signWith(SignatureAlgorithm.RS512, secret) + .signWith(SignatureAlgorithm.HS512, secret) .compact(); } /** * 从token中获取JWT中的负载 */ - Claims getClaimsFromToken(String token) { - Claims claims; + private Claims getClaimsFromToken(String token) { + Claims claims = null; try { claims = Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody(); - } finally { - claims = null; + } catch (Exception e) { + LOGGER.info("JWT格式验证失败:{}",token); } return claims; } @@ -70,9 +72,8 @@ public class JwtTokenUtil { String username; try { Claims claims = getClaimsFromToken(token); - username = claims.getSubject(); + username = claims.getSubject(); } catch (Exception e) { - e.printStackTrace(); username = null; } return username; @@ -101,14 +102,33 @@ public class JwtTokenUtil { * 从token中获取过期时间 */ private Date getExpiredDateFromToken(String token) { - Date expiredDate = null; - try { - Claims claims = getClaimsFromToken(token); - expiredDate = claims.getExpiration(); - } catch (Exception e) { - e.printStackTrace(); - } - return expiredDate; + Claims claims = getClaimsFromToken(token); + return claims.getExpiration(); } + /** + * 根据用户信息生成token + */ + public String generateToken(UserDetails userDetails) { + Map claims = new HashMap<>(); + claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername()); + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } + + /** + * 判断token是否可以被刷新 + */ + public boolean canRefresh(String token) { + return !isTokenExpired(token); + } + + /** + * 刷新token + */ + public String refreshToken(String token) { + Claims claims = getClaimsFromToken(token); + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } } diff --git a/mall-admin/src/main/resources/application.properties b/mall-admin/src/main/resources/application.properties index 98c866e..28065c6 100644 --- a/mall-admin/src/main/resources/application.properties +++ b/mall-admin/src/main/resources/application.properties @@ -32,8 +32,8 @@ spring.thymeleaf.cache=false jwt.tokenHeader=Authorization #JWTӽʹõԿ jwt.secret=mySecret -#JWTijʱ +#JWTijʱ(60*60*24) jwt.expiration=604800 #JWTõͷ -jwt.tokenHead="Bearer " +jwt.tokenHead=Bearer #===JWT end=== \ No newline at end of file