pom依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
JWT工具类
package com.auo.Utils;
import com.auo.Pojo.UacUser;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
@Slf4j
public class TokenUtils {
private final static String tokenHeader = "Authorization";
private static final long EXPIRE_TIME = 2 * 60 * 60 * 1000;
private static final String TOKEN_SECRET = "auo";
public static boolean verify(String token, String username,String dept,String userId) throws Exception {
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm)
.withClaim("username", username)
.withClaim("dept", dept)
.withClaim("userId", userId)
.build();
verifier.verify(token);
log.info("token is valid");
return true;
} catch (TokenExpiredException e) {
throw new TokenExpiredException("登录过期,请重新登录");
} catch (Exception e) {
log.info("token is invalid {}", e.getMessage());
throw new Exception(e.getMessage());
}
}
public static UacUser getUacUser(String token) {
try {
UacUser uacUser = new UacUser();
DecodedJWT jwt = JWT.decode(token);
uacUser.setDeptNo(jwt.getClaim("dept").asString());
uacUser.setName(jwt.getClaim("username").asString());
uacUser.setId(jwt.getClaim("userId").asString());
return uacUser;
} catch (JWTDecodeException e) {
log.error("error:{}", e.getMessage());
throw new JWTDecodeException(e.getMessage());
}
}
public static String getUsername(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("username").asString();
} catch (JWTDecodeException e) {
log.error("error:{}", e.getMessage());
throw new JWTDecodeException(e.getMessage());
}
}
public static String getUserId(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("userId").asString();
} catch (JWTDecodeException e) {
log.error("error:{}", e.getMessage());
throw new JWTDecodeException(e.getMessage());
}
}
public static String getUserDept(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("dept").asString();
} catch (JWTDecodeException e) {
log.error("error:{}", e.getMessage());
throw new JWTDecodeException(e.getMessage());
}
}
public static String sign(String username,String dept,String userId) throws Exception {
try {
username = username.toLowerCase();
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
return JWT.create()
.withClaim("username", username)
.withClaim("dept", dept)
.withClaim("userId", userId)
.withExpiresAt(date)
.sign(algorithm);
} catch (Exception e) {
log.error("error:", e);
throw new Exception(e.getMessage());
}
}
public static String getToken(HttpServletRequest request) {
String requestHeader = request.getHeader(tokenHeader);
String token = "";
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
token = requestHeader.substring(7);
}
return token;
}
}
请求拦截类
package com.auo.config;
import com.auo.Pojo.UacUser;
import com.auo.Utils.TokenUtils;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@Component
public class AuthKeyFilter extends OncePerRequestFilter {
private final Logger LOGGER = LoggerFactory.getLogger(AuthKeyFilter.class);
@Value("${index-url}")
private String indexUrl;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = TokenUtils.getToken(request);
if (!StringUtils.isEmpty(token)) {
boolean tokenPass = false;
try {
UacUser uacUser = TokenUtils.getUacUser(token);
if (TokenUtils.verify(token,uacUser.getName(),uacUser.getDeptNo(),uacUser.getId())){
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("user"));
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(uacUser.getId(), uacUser, authorities);
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
tokenPass = true;
}
} catch (TokenExpiredException e) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.getWriter().write("token expire");
} catch (SignatureVerificationException e) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.getWriter().write("sign invalid");
} catch (Exception e) {
LOGGER.error("AuthKeyFilter doFilterInternal Exception {}",e.toString());
response.setStatus(HttpStatus.BAD_REQUEST.value());
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.getWriter().write("token error");
}
if (!tokenPass) {
return;
}
}
filterChain.doFilter(request, response);
}
}
spring security核心配置类 配置过滤器
package com.auo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
private final AuthKeyFilter authKeyFilter;
public SecurityConfig(UserDetailsService userDetailsService, AuthKeyFilter authKeyFilter) {
this.userDetailsService = userDetailsService;
this.authKeyFilter = authKeyFilter;
}
@Override
public UserDetailsService userDetailsService() {
return userDetailsService;
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable().cors().and().addFilterBefore(authKeyFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/login/info").authenticated()
.antMatchers("/login/**").permitAll()
.antMatchers("/api/**").permitAll();
}
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
判断是否登录 tempPage为主页面 /index 跳转主页面
@GetMapping("/oneData/checkLoginStatus")
public void checkLoginStatus(HttpServletRequest request, HttpServletResponse response) throws IOException {
LOGGER.info("PostMapping /login/checkLoginStatus start");
try {
String authkey = request.getParameter("authkey");
if (StringUtil.isNotEmpty(authkey)) {
UacClientBean uacClientBean = new UacClientBean();
uacClientBean.initial();
auo.cim.uac.cli.bean.UacAuthority authority = uacClientBean.getFunctions("US", authkey);
if (!authority.isPass()){
throw new Exception("login error");
}
LOGGER.info("authority : {},{},{}",authority.getUserName(),authority.getInputAccount(),authority.getDeptNo());
UacUser uacUser = new UacUser();
uacUser.setName(authority.getUserName());
uacUser.setId(authority.getInputAccount());
uacUser.setDeptNo(authority.getDeptNo());
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("user"));
Authentication token = new UsernamePasswordAuthenticationToken(authority.getInputAccount(), uacUser, authorities);
SecurityContextHolder.getContext().setAuthentication(token);
String jwt = TokenUtils.sign(uacUser.getName(), uacUser.getDeptNo(),uacUser.getId());
LOGGER.info("jwt: {}",jwt);
String queryString = request.getQueryString();
String[] queryArr = queryString.split("&");
StringBuilder urlBuild = new StringBuilder();
for (String query : queryArr) {
if (!query.contains("tempPage")) {
urlBuild.append("&").append(URLEncoder.encode(query, "UTF-8"));
}
}
urlBuild.append("&token=").append(jwt);
urlBuild.deleteCharAt(0);
response.sendRedirect( indexUrl + "?" + urlBuild.toString());
LOGGER.info("/login/checkLoginStatus sendRedirect success, token:{}",urlBuild.toString());
}
} catch (Exception e) {
LOGGER.error("", e);
}
}
前端请求拦截
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import * as echarts from 'echarts'
import './errorSolve'
import ElementUI from 'element-ui';
import 'babel-polyfill'
import 'element-ui/lib/theme-chalk/index.css';
import 'element-ui/lib/theme-chalk/base.css';
import "./assets/css/common.css";
import axios from 'axios'
Vue.prototype.$echarts = echarts
Vue.directive('loadmore', {
bind(el, binding) {
const selectWrap = el.querySelector('.el-table__body-wrapper')
selectWrap.addEventListener('scroll', function () {
let sign = 3
const scrollDistance = this.scrollHeight - this.scrollTop - this.clientHeight
if (Math.ceil(scrollDistance) <= sign) {
binding.value()
}
})
},
})
Vue.prototype.$axios = axios
axios.defaults.headers.post['Content-Type'] = 'multipart/form-data';
axios.defaults.baseURL = window.g.ServerUrl
const service = axios.create({
baseURL: window.g.ServerUrl ,
timeout: 3000000,
withCredentials: true
})
service.interceptors.request.use(
config => {
if (localStorage.getItem('token')) {
console.log("找到token")
config.headers.Authorization = `Bearer ` + localStorage.getItem('token') ;
}
else{
console.log("没有找到token")
config.headers.Authorization = "" ;
}
return config;
},error => {
return Promise.reject(error) ;
});
service.interceptors.response.use(
response => {
console.log(response);
return response;
}, error => {
if (error.response) {
let encodeTempPage =encodeURIComponent(`${window.location.origin}/oneData/#/index`);
let targetAddress = `${axios.defaults.baseURL}/login/uacLogin?tempPage=${encodeTempPage}`;
let redirectPage = encodeURIComponent(window.location.href);
targetAddress=targetAddress+`&redirectPage=${redirectPage}`;
console.log(`targetAddress `,targetAddress);
switch (error.response.status) {
case 403:
window.location.href = targetAddress;
break;
case 500:
break;
case 400:
console.log("token expired")
window.location.href = targetAddress;
break;
default:
this.$message.error("错误状态不是403,400,500");
}
return error.response;
}
}
)
Vue.prototype.$axios = service
Vue.use(ElementUI);
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
处理返回值 将token放入本地内存
handleToken(){
console.log("212123123")
const NEW_TOKEN = this.$route.query.token;
console.log(`token `,NEW_TOKEN)
let NEW_ADDRESS = window.location.href;
if(NEW_TOKEN){
localStorage.setItem("token", NEW_TOKEN);
if (NEW_ADDRESS.indexOf('redirectPage') !== -1) {
let handleAddress = decodeURIComponent(NEW_ADDRESS);
let splice1 = handleAddress.split('redirectPage=')[1];
let splice2 = splice1.split('&')[0];
let result = splice2;
localStorage.setItem("token", NEW_TOKEN);
setTimeout(() => {
}, 200);
} else {
setTimeout(() => {
localStorage.setItem("token", NEW_TOKEN);
this.$router.push({ path: '/index' })
}, 200);
}
}
}