<dependency>
<groupId>org.springframework.mobile</groupId>
<artifactId>spring-mobile-device</artifactId>
</dependency>
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mobile.device.Device;
import org.springframework.mobile.device.DeviceResolver;
import org.springframework.mobile.device.DeviceUtils;
import org.springframework.mobile.device.LiteDeviceResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class DeviceResolverRequestFilter extends OncePerRequestFilter {
private final DeviceResolver deviceResolver;
@Autowired
private SysRoleService sysRoleService;
/**
* Create a device resolving {@link Filter} that defaults to a {@link LiteDeviceResolver} implementation.
*/
public DeviceResolverRequestFilter() {
this(new LiteDeviceResolver());
}
/**
* Create a device resolving {@link Filter}.
*
* @param deviceResolver the device resolver to delegate to.
*/
public DeviceResolverRequestFilter(DeviceResolver deviceResolver) {
this.deviceResolver = deviceResolver;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
Device device = deviceResolver.resolveDevice(request);
request.setAttribute(DeviceUtils.CURRENT_DEVICE_ATTRIBUTE, device);
String userId = TokenUtils.getUserIdByRequest(request);
boolean isSuper = sysRoleService.isSuper(userId);
request.setAttribute("isSuper",isSuper);
filterChain.doFilter(request, response);
}
}
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import javax.servlet.http.HttpServletRequest;
@SuppressWarnings("static-access")
public class TokenUtils {
private static String secret;
private static String authHeader;
static {
secret = "qwertyuiop";
authHeader = "Authorization";
}
public TokenUtils(String secret, String authHeader) {
this.secret = secret;
this.authHeader = authHeader;
}
/**
* 从HttpServletRequest中获取用户ID
*
*
*/
public static String getUserIdByRequest(HttpServletRequest request) {
return getUserIdFromToken(getToken(request));
}
/**
* 从token中获取用户ID
*
*/
private static String getUserIdFromToken(String token) {
String userId;
try {
final Claims claims = new TokenUtils(secret, authHeader).getAllClaimsFromToken(token);
userId = claims.getSubject();
} catch (Exception e) {
userId = null;
}
return userId;
}
/**
* 获取token中所有的Claims
*
*
*/
private Claims getAllClaimsFromToken(String token) {
Claims claims;
try {
claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
claims = null;
}
return claims;
}
/**
* 获取HttpServletRequest中的token
*
*/
public static String getToken(HttpServletRequest request) {
String ah = new TokenUtils(secret, authHeader).getAuthHeaderFromHeader(request);
if (ah != null && ah.startsWith("Bearer ")) {
return ah.substring(7);
}
return null;
}
/**
* 获取HttpServletRequest中定义存储token的key对应的token值
*
*/
private String getAuthHeaderFromHeader(HttpServletRequest request) {
return request.getHeader(authHeader);
}
}
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mobile.device.Device;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
/**
* token帮助类
*
*
*/
public class TokenHelper {
@Value("${spring.application.name}")
private String APP_NAME;
@Value("${jwt.secret}")
public String SECRET;
@Value("${jwt.expires_in}")
private int EXPIRES_IN;
@Value("${jwt.mobile_expires_in}")
private int MOBILE_EXPIRES_IN;
@Value("${jwt.header}")
private String AUTH_HEADER;
static final String AUDIENCE_UNKNOWN = "unknown";
static final String AUDIENCE_WEB = "web";
static final String AUDIENCE_MOBILE = "mobile";
static final String AUDIENCE_TABLET = "tablet";
private SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS512;
/**
* 从HttpServletRequest中获取用户ID
*
*/
public String getUserIdByRequest(HttpServletRequest request) {
return this.getUserIdFromToken(this.getToken(request));
}
/**
* 从token中获取用户ID
*
*
*/
private String getUserIdFromToken(String token) {
String userId;
try {
final Claims claims = this.getAllClaimsFromToken(token);
userId = claims.getSubject();
} catch (Exception e) {
userId = null;
}
return userId;
}
/**
* 获取签发时间
*
*
*/
public Date getIssuedAtDateFromToken(String token) {
Date issueAt;
try {
final Claims claims = this.getAllClaimsFromToken(token);
issueAt = claims.getIssuedAt();
} catch (Exception e) {
issueAt = null;
}
return issueAt;
}
/**
* 从token中获取Audience
*
*
*/
public String getAudienceFromToken(String token) {
String audience;
try {
final Claims claims = this.getAllClaimsFromToken(token);
audience = claims.getAudience();
} catch (Exception e) {
audience = null;
}
return audience;
}
/**
* 刷新token
*
*
*/
public String refreshToken(String token) {
String refreshedToken;
Date a = new Date();
try {
final Claims claims = this.getAllClaimsFromToken(token);
claims.setIssuedAt(a);
refreshedToken = Jwts.builder()
.setClaims(claims)
.setExpiration(generateExpirationDate(EXPIRES_IN))
.signWith(SIGNATURE_ALGORITHM, SECRET)
.compact();
} catch (Exception e) {
refreshedToken = null;
}
return refreshedToken;
}
/**
* 生成token
*
*
*/
public String generateToken(String userId, Device device) {
String audience = generateAudience(device);
return Jwts.builder()
.setIssuer(APP_NAME)
.setSubject(userId)
.setAudience(audience)
.setIssuedAt(new Date())
.setExpiration(generateExpirationDate(EXPIRES_IN))
.signWith(SIGNATURE_ALGORITHM, SECRET)
.compact();
}
/**
* 根据请求客户端生成audience
*
*
*/
private String generateAudience(Device device) {
String audience = AUDIENCE_UNKNOWN;
if (device.isNormal()) {
audience = AUDIENCE_WEB;
} else if (device.isTablet()) {
audience = AUDIENCE_TABLET;
} else if (device.isMobile()) {
audience = AUDIENCE_MOBILE;
}
return audience;
}
/**
* 获取token中所有的Claims
*
*
*/
private Claims getAllClaimsFromToken(String token) {
Claims claims;
try {
claims = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
claims = null;
}
return claims;
}
/**
* 获取token失效时间
*
*
*/
public Date getExpirationDateFromToken(String token) {
Date expiration;
HashMap hm=new HashMap();
try {
final Claims claims = this.getAllClaimsFromToken(token);
expiration = claims.getExpiration();
} catch (Exception e) {
expiration = null;
}
return expiration;
}
/**
* 设置token失效时间
*
*
*/
private Date generateExpirationDate(int expiresIn) {
expiresIn = expiresIn * 1000 * 60;
return new Date(System.currentTimeMillis() + expiresIn);
}
/**
* 判断token是否失效
*
*/
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
/**
* 校验token是否合法
*
*
*/
public Boolean validateToken(String token) {
return isTokenExpired(token);
}
/**
* 获取HttpServletRequest中的token
*
*
*/
public String getToken(HttpServletRequest request) {
String authHeader = getAuthHeaderFromHeader(request);
if (authHeader != null && authHeader.startsWith("Bearer ")) {
return authHeader.substring(7);
}
return null;
}
/**
* 获取HttpServletRequest中定义存储token的key对应的token值
*
*
*/
public String getAuthHeaderFromHeader(HttpServletRequest request) {
return request.getHeader(AUTH_HEADER);
}
/**
* 获取token有效时长
*
*
*/
public int getExpiredIn() {
return EXPIRES_IN;
}
/**
* 获取token有效时长
*
*/
public int getMobileExpiresIn() {
return MOBILE_EXPIRES_IN;
}
}
# jwt鉴权设置
jwt:
header: Authorization
# token过期时间,单位为分钟
expires_in: 1440
# 手机端token过期时间,单位为分钟
mobile_expires_in: 10080
secret: qwertyuiop
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mobile.device.Device;
import org.springframework.mobile.device.DeviceUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
* 登录处理类
*
*
*/
@Slf4j
@RestController
@RequestMapping("auth")
@Api(tags = "登录模块", produces = "登录模块Api")
public class LoginController {
@Autowired
private TokenHelper tokenHelper;
@Autowired
private SysUserService sysUserService;
@ResponseBody
@PostMapping("/login")
@ApiOperation(value = "用户登录", notes = "用户登录的方法")
public Object login(@RequestBody AuthenticationRequest authenticationRequest, HttpServletRequest request, HttpServletResponse response) {
log.error("Request Json:" + JSON.toJSONString(authenticationRequest));
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(authenticationRequest.getUsername(), authenticationRequest.getPassword());
Subject subject = SecurityUtils.getSubject();
ResultData resultData = new ResultData();
try {
if (!subject.isAuthenticated()) {
subject = (new Subject.Builder()).buildSubject();
ThreadContext.bind(subject);
}
// 该方法会调用JwtRealm中的doGetAuthenticationInfo方法
subject.login(usernamePasswordToken);
resultData.setCode(0).setMsg("登录成功");
} catch (UnknownAccountException exception) {
resultData.setCode(1).setMsg("帐号不存在");
} catch (IncorrectCredentialsException exception) {
resultData.setCode(2).setMsg("错误的凭证,用户名或密码不正确");
} catch (LockedAccountException exception) {
resultData.setCode(3).setMsg("账户已锁定");
} catch (ExcessiveAttemptsException exception) {
resultData.setCode(4).setMsg("错误次数过多");
} catch (AuthenticationException exception) {
resultData.setCode(5).setMsg("认证失败");
}
// 认证通过
if (subject.isAuthenticated()) {
SysUser sysUser = sysUserService.getUserByUsername(authenticationRequest.getUsername());
//生成token
String token = tokenHelper.generateToken(sysUser.getId(), DeviceUtils.getCurrentDevice(request));
/**
* 根据登录的设备类型设置token过期时间
*/
int expiresIn;
Device device = DeviceUtils.getCurrentDevice(request);
if (device.isMobile() || device.isTablet()) {
expiresIn = tokenHelper.getMobileExpiresIn();
Map dataMap = new HashMap(4);
dataMap.put("name", sysUser.getName());
dataMap.put("icon", sysUser.getImgHref());
dataMap.put("token", token);
resultData.setData(dataMap);
} else {
expiresIn = tokenHelper.getExpiredIn();
resultData.setData(new UserTokenState(token, expiresIn));
}
return resultData;
} else {
return resultData;
}
}
}