-
目前用户的登录解决方案,就是用户输入账号密码进到接口验证正确后系统生成一串带有时效性的字符串。下次用户在访问一些需要用户登录才能访问的接口时就不用携带用户的账号密码再进行身份验证,只需要验证当前存在cookie或者session里的token还有效吗?如果有效就在请求接口的时候带着这串字符串一起进来访问,我们可以重写登录拦截器进行token匹配。如果通过就继续访问用户要访问的接口,如果不通过可以返回自己自定义的提示语或者直接转到登陆页。
-
以下下是代码实现,登录接口:
@RestController public class LoginController { @Autowired private UserInterface userInterface; @Autowired private JwtHelper jwtHelper; @Autowired private UploadInterface uploadInterface; @ApiOperation(value = "登录验证接口") @RequestMapping(value = "/login", method = RequestMethod.POST) public ResParameter CheckLogin(@RequestBody UserEntity user, HttpServletRequest request) { ResParameter res = new ResParameter(); String pass = DigestUtils.md5DigestAsHex(user.getPassword().getBytes()); UserEntity userEntity = userInterface.GetEntityByPassword(user.getAccount(), pass); if (userEntity == null) { res.setCode(500); res.setInfo("登录失败,请检查用户名或者密码是否正确!"); return res; } else { res.setCode(200); res.setAccount(userEntity.getAccount()); res.setName(userEntity.getName()); res.setInfo("登录成功!"); res.setToken(jwtHelper.sign(user.getAccount(), userEntity.getId())); request.removeAttribute("UserInfo"); request.getSession().setAttribute("UserInfo", userEntity); return res; } } }
2.分发token和验证token
@Service
public class JwtHelper {
//token过期时间目前暂时是15分钟
private static final long EXPIRE_TIME = 15 * 60 * 1000;
//公共密钥
private static final String TOKEN_SECRET = "wddcdfdfhjtjthjdffsdfsd33hcskdncksndcnsnsvsdcsdc";
//生成token
public static String sign(String username, String userid) {
String token = null;
try {
//过期时间
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
//私钥及加密算法
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
//设置头部信息
Map<String, Object> header = new HashMap<>(2);
header.put("typ", "JWT");
header.put("alg", "HS256");
//附带username,userid等信息
token = JWT.create()
.withHeader(header)
.withClaim("username", username)
.withClaim("userid", userid)
.withExpiresAt(date)
.sign(algorithm);
} catch (JWTCreationException ex) {
ex.printStackTrace();
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
}
return token;
}
//验证是否登录状态
public static boolean verify(String token) {
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception ex) {
return false;
}
}
}
3.登录拦截器
@Component
//preHandle方法(预处理)
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
boolean status = false;
response.setCharacterEncoding("utf-8");
String token = request.getHeader("accessToken");
if (null != token) {
boolean result = jwtHelper.verify(token);//验证token有效
if (result) {
status = true;
}
String url = request.getRequestURI();
if (url.equals("/getlogin")) {//如果token无效就直接跳转到登陆页或主页
response.sendRedirect(request.getContextPath() + "/getindex");
}
}
return status;
}
//postHandle方法(返回处理)
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
//afterCompletion方法(后处理)
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
4.配置接口,有些需要登录验证,有些不需要,如游客可以访问大厅主页。
@Component
//通过@Configuration声明配置类,实现WebMvcConfigurer 接口中的 addInterceptors()添加自定义的拦截器;
@Configuration
public class WebConfigurer implements WebMvcConfigurer
{
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry)
{
List<String> exclude=new ArrayList<String>();
exclude.add("/getlogin");
exclude.add("/getregister");
exclude.add("/getindex");
exclude.add("/login");
exclude.add("/register");
exclude.add("/logout");
exclude.add("/get/**");
// addPathPatterns("/**") 表示拦截所有的请求,
// excludePathPatterns("/login", "/register") 表示除了登陆与注册之外,因为登陆注册不需要登陆token也可以访问这些接口,还有带有get的下级的接口都可以不经过登录就访问。
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(exclude);
//super.addInterceptors(registry);
}
//配置静态资源(不然页面报404,会被拦截过滤)
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static");
}
}
总结:实现这个功能在网上查询了很多经验做法。算了遇到什么解决什么的一个经历。因为框架问题会遇到很多注解的变化,配置的变化。还是要多看看别人是怎么解决的。记录下来,不要忘记。