filter
package com.cwl.userdata.filter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cwl.userdata.content.Constants;
import com.cwl.userdata.util.JwtTokenUtil;
import io.jsonwebtoken.Claims;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.security.auth.Subject;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
/**
* @author LJQ E-mail:lijinquan@ishumei.com
* @version 1.0
* @date 创建时间:2018/11/12 16:36
*/
@Component
@Order(0)//指定过滤器的顺序 值越小越靠前
@WebFilter(urlPatterns = "/api/**", filterName = "tokenFilter")
public class TokenFilter extends OncePerRequestFilter {
private final Logger logger = LoggerFactory.getLogger(TokenFilter.class);
private final String[] noFilters = {"/api/excel", "/webdashboard/index", "doc", "/api/login","/csv/getToken",
"/webjars/bycdao-ui/", "/swagger", "/json", ".js", ".css", ".ico", ".jpg", ".png",
".html", "/api/csv/download", "/api/csv/v2/download"};
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
String uri = httpServletRequest.getRequestURI();
System.out.println(uri);
for (String s : noFilters) {
if (uri.contains(s)) {
//uri中包含不过滤uri,则不进行过滤
logger.info(">>>>>>>>>>>>>>>>>>>>>>>>放行url:" + uri);
filterChain.doFilter(httpServletRequest, httpServletResponse);
return;
}
}
//获得头信息token
String token = httpServletRequest.getHeader(Constants.JWT_HEADER);
//如果token不为空且以特定的TOKEN_HEADER开头
JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();
if (token != null && (!"".equals(token)) && token.startsWith(Constants.JWT_TOKEN_HEADER)) {
//对请求进行路由
String jwt = "";
try {
jwt = token.substring(Constants.JWT_TOKEN_HEADER.length());
} catch (Exception e) {
//不对其进行路由
httpServletResponse.setStatus(200);
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.getWriter().write("{\"code\":400,\"msg\":\"请重新登录!\",\"data\":null}");
return;
}
if ("".equals(jwt)) {
//不对其进行路由
httpServletResponse.setStatus(200);
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.getWriter().write("{\"code\":400,\"msg\":\"请重新登录!\",\"data\":null}");
return;
}
Claims claims = jwtTokenUtil.parseJWT(jwt);
//验证token是否过期
if (claims.getExpiration().before(new Date())) {
this.logger.info("TokenFilter:token已过期");
httpServletResponse.setStatus(200);
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.setContentType("{\"code\":300,\"msg\":\"请重新登录!\",\"data\":null}");
return;
}
//验证token拥有者是否有效
if (!claims.getIssuer().equals(Constants.JWT_ISSUSER)) {
this.logger.info("TokenFilter:token发行者无效");
httpServletResponse.setStatus(200);
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.getWriter().write("{\"code\":300,\"msg\":\"请重新登录!\",\"data\":null}");
return;
}
String subject = claims.getSubject();
Map maps = (Map) JSON.parse(subject);
httpServletRequest.setAttribute("user", maps.get("user"));
httpServletRequest.setAttribute("provinceCode", maps.get("provinceId"));
filterChain.doFilter(httpServletRequest, httpServletResponse);
} else {
//不对其进行路由
httpServletResponse.setStatus(200);
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.getWriter().write("{\"code\":400,\"msg\":\"请重新登录!\",\"data\":null}");
}
}
}
login
package com.cwl.userdata.controller;
import com.cwl.userdata.aspect.OperatorType;
import com.cwl.userdata.aspect.OperatorLog;
import com.cwl.userdata.aspect.TabType;
import com.cwl.userdata.content.Constants;
import com.cwl.userdata.entity.Account;
import com.cwl.userdata.service.AccountService;
import com.cwl.userdata.service.ProvinceService;
import com.cwl.userdata.util.JwtTokenUtil;
import com.cwl.userdata.vo.ResponseBean;
import com.cwl.userdata.vo.login.LoginVo;
import com.cwl.userdata.vo.login.UpdateUserVo;
import com.cwl.userdata.vo.login.UserVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
/**
* @author ljq
* @date 2020-01-11 11:50
* @describe
*/
@RestController
@RequestMapping("/api")
@Api(tags = "登录接口")
public class LoginController {
@Resource
private AccountService accountService;
@Resource
private ProvinceService provinceService;
@PostMapping("/login")
@ApiOperation(value = "登录接口")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "success", response = UserVo.class),
@ApiResponse(code = 501, message = "用户名或密码错误!"),
@ApiResponse(code = 502, message = "验证码输入错误!"),
@ApiResponse(code = 503, message = "未知错误!")
})
@OperatorLog(value = OperatorType.LOGIN, operatorModel = TabType.LOGIN)
public ResponseBean login(@RequestBody LoginVo loginVo,
HttpServletRequest request) {
String userAccount = loginVo.getUsername();
String validCode = loginVo.getValidCode();
try {
HttpSession session = request.getSession(true);
//检查验证码
String sessionValidCode = (String) session.getAttribute(Constants.RAND_VALID_CODE);
if (!StringUtils.isEmpty(validCode) && validCode.equalsIgnoreCase(sessionValidCode)) {
Account a = new Account();
a.setPassword(loginVo.getPassword());
a.setUsername(loginVo.getUsername());
Account account = accountService.login(a);
if (null != account) {
//生成token
JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();
String subject = JwtTokenUtil.generalSubject(account.getUsername(), account.getProvinceId());
String token = jwtTokenUtil.createJWT(userAccount, subject, Constants.JWT_TTL);
//将token返回
UserVo userVo = new UserVo();
userVo.setAccount(account);
userVo.setToken(token);
userVo.setProvinces(provinceService.getProvinces(account.getProvinceId()));
return ResponseBean.builder().code(200).data(userVo).msg("OK").build();
}
return ResponseBean.builder().code(501).data(false).msg("用户名或密码错误").build();
} else {
return ResponseBean.builder().code(502).msg("验证码输入错误!").data(false).build();
}
} catch (Exception e) {
return ResponseBean.builder().code(503).msg("未知错误!").build();
}
}
@PostMapping("/csv/getToken")
@OperatorLog(value = OperatorType.LOGIN, operatorModel = TabType.LOGIN)
public ResponseBean getToken(@RequestBody LoginVo loginVo,HttpServletRequest request) {
String userAccount = loginVo.getUsername();
try {
Account a = new Account();
a.setPassword(loginVo.getPassword());
a.setUsername(loginVo.getUsername());
Account account = accountService.login(a);
if (null != account) {
//生成token
JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();
String subject = JwtTokenUtil.generalSubject(account.getUsername(), account.getProvinceId());
String token = jwtTokenUtil.createJWT(userAccount, subject, Constants.JWT_TTL);
//将token返回
Map<String, String> map = new HashMap<>(1);
map.put("token", token);
return ResponseBean.builder().code(200).data(map).msg("OK").build();
}
return ResponseBean.builder().code(501).data(false).msg("用户名或密码错误").build();
} catch (Exception e) {
e.printStackTrace();
return ResponseBean.builder().code(503).msg("未知错误!").build();
}
}
@GetMapping("/login/validcode")
@ApiOperation(value = "获取验证码")
public ResponseBean validcode(HttpServletRequest request) {
Random random = new Random();
StringBuilder sRand = new StringBuilder();
for (int i = 0; i < 4; i++) {
String rand = String.valueOf(random.nextInt(10));
sRand.append(rand);
}
// 将认证码存入SESSION
request.getSession().setAttribute(Constants.RAND_VALID_CODE, sRand.toString());
return ResponseBean.builder().code(200).msg("OK").data(sRand.toString()).build();
}
private Account getAccount(UpdateUserVo updateUserVo) {
Account account = new Account();
account.setUsername(updateUserVo.getUsername());
account.setPassword(updateUserVo.getOldPassword());
return account;
}
@ApiOperation(value = "验证旧密码正确")
@PostMapping("/login/password")
public ResponseBean getAccountByPassword(@RequestBody UpdateUserVo updateUserVo) {
Account account = getAccount(updateUserVo);
Account a = accountService.login(account);
if (a == null) {
return ResponseBean.builder().code(200).data(false).msg("旧密码错误").build();
}
return ResponseBean.builder().code(200).data(true).msg("旧密码正确").build();
}
@ApiOperation(value = "修改密码")
@PostMapping("/login/password/update")
@OperatorLog(value = OperatorType.UPDATE_PASSWORD, operatorModel = TabType.UPDATE_PASSWORD)
public ResponseBean updatePassword(@RequestBody UpdateUserVo updateUserVo, HttpServletRequest request) {
if (!updateUserVo.getNewPassword().equals(updateUserVo.getReNewPassword())) {
return ResponseBean.builder().code(503).msg("重复输入密码不一致").build();
}
Account account = getAccount(updateUserVo);
Account a = accountService.login(account);
if (a == null) {
return ResponseBean.builder().code(502).data(false).msg("旧密码错误").build();
}
a.setPassword(updateUserVo.getNewPassword());
if (accountService.updatePassword(a)) {
//修改操作录入数据库操作日志
return ResponseBean.builder().code(200).msg("OK").build();
}
return ResponseBean.builder().code(501).msg("修改密码失败").build();
}
@PostMapping("/login/cz")
@ApiOperation(value = "财政登录接口")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "success", response = UserVo.class),
@ApiResponse(code = 501, message = "用户名或密码错误!"),
@ApiResponse(code = 502, message = "验证码输入错误!"),
@ApiResponse(code = 503, message = "未知错误!")
})
public ResponseBean czLogin(@RequestBody LoginVo loginVo,
HttpServletRequest request) {
String userAccount = loginVo.getUsername();
String validCode = loginVo.getValidCode();
try {
HttpSession session = request.getSession(true);
//检查验证码
String sessionValidCode = (String) session.getAttribute(Constants.RAND_VALID_CODE);
if (!StringUtils.isEmpty(validCode) && validCode.equalsIgnoreCase(sessionValidCode)) {
Account a = new Account();
a.setPassword(loginVo.getPassword());
a.setUsername(loginVo.getUsername());
Account account = accountService.loginCz(a);
if (null != account) {
//生成token
JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();
String subject = JwtTokenUtil.generalSubject(account.getUsername(), account.getProvinceId());
String token = jwtTokenUtil.createJWT(userAccount, subject, Constants.JWT_TTL);
//将token返回
UserVo userVo = new UserVo();
userVo.setAccount(account);
userVo.setToken(token);
userVo.setProvinces(provinceService.getProvinces(account.getProvinceId()));
return ResponseBean.builder().code(200).data(userVo).msg("OK").build();
}
return ResponseBean.builder().code(501).data(false).msg("用户名或密码错误").build();
} else {
return ResponseBean.builder().code(502).msg("验证码输入错误!").data(false).build();
}
} catch (Exception e) {
return ResponseBean.builder().code(503).msg("未知错误!").build();
}
}
}
token
package com.cwl.userdata.controller;
import com.cwl.userdata.content.Constants;
import com.cwl.userdata.util.JwtTokenUtil;
import com.cwl.userdata.vo.ResponseBean;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* @author ljq
* @date 2019-10-15 11:03
* @describe
*/
@RestController
@RequestMapping("/api/token")
@Api(tags = "token验证")
public class TokenController {
@ApiOperation(value = "token验证", notes = "大监控所有接口的有效性验证,通过登录时返回的'token'值进行权限验证")
@GetMapping
public ResponseBean testToken(HttpServletRequest httpServletRequest) {
//获得头信息token
String token = httpServletRequest.getHeader(Constants.JWT_HEADER);
//如果token不为空且以特定的TOKEN_HEADER开头
JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();
if (token != null && (!"".equals(token)) && token.startsWith(Constants.JWT_TOKEN_HEADER)) {
//对请求进行路由
String jwt = token.substring(Constants.JWT_TOKEN_HEADER.length());
System.out.println(jwt);
return ResponseBean.builder().code(200).msg("OK").data(jwt).build();
}
return ResponseBean.builder().code(500).msg("token验证失败").build();
}
}
util
package com.cwl.userdata.util;
import com.alibaba.fastjson.JSONObject;
import com.cwl.userdata.content.Constants;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
/**
* @author LJQ E-mail:lijinquan@ishumei.com
* @version 1.0
* @date 创建时间:2018/11/12 17:12
* @parameter
* @return
* @since
*/
public class JwtTokenUtil {
public SecretKey generalKey() {
String stringKey = Constants.JWT_SECERT;
byte[] encodedKey = Base64.decodeBase64(stringKey);
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
/**
* 创建jwt
*
* @param id
* @param subject
* @param ttlMillis
* @return
*/
public String createJWT(String id, String subject, long ttlMillis) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
SecretKey key = generalKey();
JwtBuilder builder = Jwts.builder()
.setId(id)
.setIssuedAt(now)
.setSubject(subject)
.signWith(signatureAlgorithm, key)
.setIssuer(Constants.JWT_ISSUSER);
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date exp = new Date(expMillis);
builder.setExpiration(exp);
}
return builder.compact();
}
/**
* 解密jwt
*
* @param jwt
* @return
*/
public Claims parseJWT(String jwt) {
SecretKey key = generalKey();
Claims claims = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(jwt).getBody();
return claims;
}
/**
* 生成subject信息
*
* @param
* @return
*/
public static String generalSubject(String user, String provinceCode) {
JSONObject jo = new JSONObject();
jo.put("user", user);
jo.put("provinceId", provinceCode);
return jo.toJSONString();
}
}