# pom.xml
<!--jwt-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.0</version>
</dependency>
<!--<shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
# JwtToken
import org.apache.shiro.authc.AuthenticationToken;
public class JwtToken implements AuthenticationToken {
private String token;
public JwtToken(String token) {
this.token = token;
}
@Override
public Object getPrincipal() {
return token;
}
@Override
public Object getCredentials() {
return token;
}
}
# JwtUtil
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.interfaces.DecodedJWT;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
public class JwtUtil {
private static final long EXPIRE_TIME = 3 * 60 * 60 * 1000;
public static boolean verify(String token, String username, String secret) {
try {
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm)
.withClaim("username", username)
.build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception exception) {
return false;
}
}
public static String getUsername(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("username").asString();
} catch (JWTDecodeException e) {
return null;
}
}
public static String sign(String username, String secret) {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(secret);
return JWT.create()
.withClaim("username", username)
.withExpiresAt(date)
.sign(algorithm);
}
public static void signOut(HttpServletRequest request, HttpServletResponse response) {
if (request.getCookies() != null) {
for(Cookie cookie : request.getCookies()){
if(cookie.getName().equals("token")){
cookie.setValue(null);
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);
break;
}
}
}
}
}
# JwtFilter
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JwtFilter extends BasicHttpAuthenticationFilter {
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
try {
executeLogin(request, response);
return true;
} catch (Exception e) {
return false;
}
}
@Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String token = "";
Cookie[] cookies = httpServletRequest.getCookies();
if (cookies != null) {
for(Cookie cookie : cookies) {
if(cookie.getName().equals("token")) {
token = cookie.getValue();
}
}
}
JwtToken jwtToken = new JwtToken(token);
getSubject(request, response).login(jwtToken);
return true;
}
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
httpServletResponse.setStatus(HttpStatus.OK.value());
return false;
}
return super.preHandle(request, response);
}
}
# ShiroRealm
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ShiroRealm extends AuthorizingRealm {
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JwtToken;
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = JwtUtil.getUsername(principals.toString());
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
return simpleAuthorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
String token = (String) auth.getCredentials();
String username = JwtUtil.getUsername(token);
if (username == null) {
throw new AuthenticationException("token无效");
}
UserBean userBean = userService.queryByUser(username);
if (userBean == null) {
throw new AuthenticationException("用户不存在!");
}
if (!JwtUtil.verify(token, username, userBean.getPassword())) {
throw new AuthenticationException("用户名或密码错误");
}
return new SimpleAuthenticationInfo(token, token, "shiro_realm");
}
}
# ShiroConfig
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("/api/user/login", "anon");
filterChainDefinitionMap.put("/api/user/logout", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/swagger**/**", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/v2/**", "anon");
Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
filterMap.put("jwt", new JwtFilter());
shiroFilterFactoryBean.setFilters(filterMap);
//<!-- 过滤链定义,从上向下顺序执行,一般将
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
securityManager.setSubjectDAO(subjectDAO);
securityManager.setRealm(shiroRealm);
return securityManager;
}
}
# 在controller 层判断登录,如果登录成功就把cookie: “token” 发送到前端,每次请求都拦截cookie来检查 token
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
@Api(value = "用户表接口")
@RestController
@RequestMapping("/api/user")
public class UserController extends BaseApiController {
@Autowired
private UserService userService;
@ApiOperation("根据id查询用户信息")
@RequiresPermissions("user:query")
@GetMapping("/query")
public Map<String, Object> queryById(Long id) {
return resp(200, "查询成功", userService.queryById(id));
}
@ApiOperation("根据账号查询用户")
@GetMapping("/query/user")
public Map<String, Object> queryByName(String user) {
return resp(200, "查询成功", userService.queryByUser(user));
}
@ApiOperation("用户登录")
@PostMapping("/login")
public Map<String, Object> login (HttpServletResponse response, String user, String password) throws IOException {
UserBean userBean = userService.queryByUser(user);
if (userBean != null) {
if (password.equals(userBean.getPassword())) {
Cookie cookie = new Cookie("token", URLEncoder.encode(JwtUtil.sign(user, password),"UTF-8"));
cookie.setPath("/");
response.addCookie(cookie);
return resp(200,"登录成功", userBean);
} else {
return resp(10011,"密码错误");
}
}
return resp(10001, "没有该用户");
}
@ApiOperation("用户退出登录")
@GetMapping("/logout")
public Map<String, Object> logout(HttpServletRequest request, HttpServletResponse response) {
JwtUtil.signOut(request, response);
return resp(200, "退出登录成功");
}
}