文章目录

  • 前言
  • 一、基于Token的身份认证工作流程
  • 二、实现步骤
    • 1.配置过滤请求
    • 2.实现过滤器
    • 3.登录接口
    • 4.登录之后获取用户信息
  • 总结

前言

基于Token的身份认证是无状态的,服务器或者Session中不会存储任何用户信息。


一、基于Token的身份认证工作流程

1.用户通过用户名和密码请求访问

2.服务器验证用户,通过校验则向客户端返回一个token

3.客户端存储token,并且在随后的每一次请求中都带着它

4.服务器校验token并返回数据

每一次请求都需要token -Token应该放在请求header中 -我们还需要将服务器设置为接受来自所有域的请求,用Access-Control-Allow-Origin: *

二、实现步骤

1.配置过滤请求

在web-xml中配置需要认证的请求

<filter><filter-name>authFilter</filter-name><filter-class>com.demo.filter.AuthFilter</filter-class><init-param><param-name>ignore</param-name><param-value>/**</param-value></init-param><init-param><param-name>noIgnore</param-name><param-value>/**/userApi/**/**</param-value></init-param></filter>

2.实现过滤器

代码如下(示例):

public class AuthFilter implements Filter {protected Pattern[] ignorePattern = null;PathMatcher matcher = new AntPathMatcher();// 不用过滤的请求String[] ignoreStrs = null;// 需要过滤的请求String[] noIgnoreStrs = null;public AuthFilter() {}@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest)servletRequest;HttpServletResponse response = (HttpServletResponse)servletResponse;String uri = request.getRequestURI();// 判断是否需要认证if (this.checkIgnore(uri) && !this.checkNoIgnore(uri)) {chain.doFilter(request, response);} else {// 用户认证Author.checkAuthorLocal(request, response, chain);}}@Overridepublic void init(FilterConfig config) throws ServletException {String ignore = config.getInitParameter("ignore");String noIgnore = config.getInitParameter("noIgnore");ignore = StringUtils.defaultIfEmpty(ignore, "");this.ignoreStrs = ignore.replaceAll("\\s", "").split(",");this.noIgnoreStrs = noIgnore.replaceAll("\\s", "").split(",");}public boolean checkIgnore(String requestUrl) {boolean flag = false;String[] var6 = this.ignoreStrs;int var5 = this.ignoreStrs.length;for(int var4 = 0; var4 < var5; ++var4) {String pattern = var6[var4];if (flag = this.matcher.match(pattern, requestUrl)) {break;}}return flag;}public boolean checkNoIgnore(String requestUrl) {boolean flag = false;String[] var6 = this.noIgnoreStrs;int var5 = this.noIgnoreStrs.length;for(int var4 = 0; var4 < var5; ++var4) {String pattern = var6[var4];if (flag = this.matcher.match(pattern, requestUrl)) {break;}}return flag;}
}

简单认证的实现类

public class Author {public Author() {}public static void checkAuthorLocal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {if (!request.getMethod().equals("OPTIONS")) {// 获取tokenString token = request.getHeader("oauth_token");if (!StringUtil.hasText(token)) {token = request.getParameter("oauth_token");}String loginUserId;if (StringUtil.hasText(token)) {// 判断token有效性loginUserId = getLoginUserId(token);if (StringUtil.hasText(loginUserId)) {setLoginUserId(token, loginUserId);chain.doFilter(request, response);} else {response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);PrintWriter writer = response.getWriter();writer.print("no access");return;}} else {response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);PrintWriter writer = response.getWriter();writer.print("no access");return;}}}private static String getLoginUserId(String accessToken) {String userId = RedisClient.get(accessToken);return userId;}public static void setLoginUserId(String accessToken, String userId) {try {RedisClient.set(accessToken, userId, Cluster.getTimeoutSecond());} catch (Exception var3) {var3.printStackTrace();}}
}
 if (!request.getMethod().equals("OPTIONS")) {...}

这段代码主要是解决后端接收不到前端传入的header参数信息的问题,前面也提过。

用户存储的工具类
代码如下(示例):

public class AuthSessionContext extends UserSessionContext {public static String USER_KEY = "userKey";public static String CACHE_KEY_USER_IDENTITY = "USER_IDENTITY_DATA";public static String CACHE_KEY_USER_IDENTITY_ID = "USER_IDENTITY_ID";//private static ICaheManager RedisClient = CacheManagerFactory.getCentralizedCacheManager();public static UserSessionContextService getContextService() {return (UserSessionContextService) BeanManager.getBean(UserSessionContextService.class);}/** @deprecated */@Deprecatedpublic static String getLoginPersonKey(HttpServletRequest request) {return getLoginUserId(request);}public static String getLoginIdentityId(HttpServletRequest request) {String loginUserId = getLoginUserId(request);String loginIdentityId = (String) RedisClient.get(CACHE_KEY_USER_IDENTITY_ID + loginUserId);if (!StringUtil.hasText(loginIdentityId)) {UserIdentityVO identity = getIdentity();if (identity != null) {loginIdentityId = identity.getId();RedisClient.set(CACHE_KEY_USER_IDENTITY_ID + loginUserId, loginIdentityId, 60);}}return loginIdentityId;}public static String getLoginIdentityId() {HttpServletRequest request = WsbpWebContextListener.getRequest();return getLoginIdentityId(request);}public static String getIdentityId() {UserIdentityVO identity = getIdentity();return identity != null ? identity.getId() : "";}public static void setLoginIdentityId(String loginUserId, String loginIdentityId) {RedisClient.set(CACHE_KEY_USER_IDENTITY_ID + loginUserId, loginIdentityId, Cluster.getTimeoutMillisecond());}public static String getLoginUserId(HttpServletRequest request) {String token = request.getHeader("oauth_token");String userId = null;if (token != null && !token.isEmpty()) {userId = (String)RedisClient.get(token);}return userId;}public static String getLoginUserId() {HttpServletRequest request = WsbpWebContextListener.getRequest();return getLoginUserId(request);}public static String getLoginUserName() {UserVO loginUser = getLoginUser();return loginUser != null ? loginUser.getUserName() : "";}public static UserVO getLoginUser() {return getContextService().getUserByUserId(getLoginUserId());}public static String getLoginDepartment(HttpServletRequest request) {String identityId = getLoginIdentityId(request);return getContextService().getLoginDepartment(identityId);}public static String getDeptId() {HttpServletRequest request = WsbpWebContextListener.getRequest();String identityId = getLoginIdentityId(request);return getContextService().getLoginDepartment(identityId);}public static DepartmentVO getDept() {return getContextService().getDepartment(getDeptId());}public static String getDeptName() {DepartmentVO department = getDept();return department != null ? department.getName() : "";}public static String getLoginOrganization(HttpServletRequest request) {String identityId = getLoginIdentityId(request);return getContextService().getLoginOrganization(identityId);}public static String getOrgId() {HttpServletRequest request = WsbpWebContextListener.getRequest();String identityId = getLoginIdentityId(request);return getContextService().getLoginOrganization(identityId);}public static OrganizationVO getOrg() {DepartmentVO dept = getDept();return dept != null ? dept.getOrg() : null;}public static String getOrgName() {OrganizationVO org = getOrg();return org != null ? org.getName() : "";}public static boolean isInAnyRole(HttpServletRequest request, String roles) {String identityId = getLoginIdentityId(request);return getContextService().checkIsInAnyRole(identityId, roles);}public static boolean isInRole(HttpServletRequest request, String roles) {String identityId = getLoginIdentityId(request);return getContextService().checkIsInRole(identityId, roles);}public static List<RoleVO> getRoleListInRoles(HttpServletRequest request, String roles) {String identityId = getLoginIdentityId(request);return getContextService().getRoleListInRoles(identityId, roles);}public static boolean isInAnyCase(HttpServletRequest request, String cases) {String identityId = getLoginIdentityId(request);return getContextService().checkIsInAnyCase(identityId, cases);}public static boolean isInCase(HttpServletRequest request, String cases) {String identityId = getLoginIdentityId(request);boolean checkIsInCase = getContextService().checkIsInCase(identityId, cases);return checkIsInCase;}public static List<RoleVO> getmyUserRoleList(HttpServletRequest request) {String identityId = getLoginIdentityId(request);return getContextService().getmyUserRoleList(identityId);}public static RoleVO getmyUserhighestRole(HttpServletRequest request) {String identityId = getLoginIdentityId(request);return getContextService().getmyUserhighestRole(identityId);}public static String getmyTenementIdByUserId(HttpServletRequest request) {String userId = getLoginUserId(request);return getContextService().getLoginTenementId(userId);}public static void setLoginUser(HttpServletResponse response, TsysUserVO user, String userKey) {try {String userId = user.getId();addCookie(response, USER_KEY, userKey, "/", getSessionTimeout());//单位分钟addCookie(response, Cluster.SESSION_KEY, userKey, "/", getSessionTimeout());//单位分钟RedisClient.set(userKey, userId, Cluster.getTimeoutSecond());//单位秒RedisClient.set(userKey+"Username", user.getUserName(), Cluster.getTimeoutSecond());//单位秒RedisClient.set(user.getUserName(), user.getPasswd(), Cluster.getTimeoutSecond());//单位秒} catch (Exception e) {e.printStackTrace();}}private static void addCookie(HttpServletResponse response, String name, String value, String path, int maxAge) {Cookie cookie = new Cookie(name, value);cookie.setPath(path);cookie.setMaxAge(maxAge);response.addCookie(cookie);}

3.登录接口

登录逻辑判断用户名密码,通过则将用户信息返回,同时将用户信息存在Redis中,向前端返回token
代码如下(示例):

 @RequestMapping(value = "/login", method = RequestMethod.POST, produces = "application/json;charset=utf-8")@ResponseBodypublic String login(@RequestBody String jsonStr, HttpServletResponse response) {JSONObject object = JSON.parseObject(jsonStr);String account = object.getString("account");String password = object.getString("password");JSONObject result = new JSONObject(3);if (StringUtils.isEmpty(account) || StringUtils.isEmpty(password)) {result .put("state", false);result .put("msg", "账号或密码不能为空");return result.toString();}// 判断用户名和密码User userInfo = userService.login(account, password);if (userInfo instanceof String) {return (String) userInfo;} else {User user = (User) userInfo;String id = user.getId();String s = id + System.currentTimeMillis();String token = MD5Util.MD5(s);Author.setLoginUserId(token, user.getId());AuthSessionContext.setLoginUser(response, user, token);result .put("state", true);result .put("oauth_token", token);}return result.toString();}

4.登录之后获取用户信息

通过扩展工具类获取信息。
代码如下(示例):

String userId = AuthSessionContext.getLoginUserId();
User userInfo = AuthSessionContext.getLoginUser();

总结

基于token最直观的好处就是无状态和可扩展性,token可以设置过期时间,超过时间之后,用户将重新登录。还可以根据相同的授权许可使特定的token甚至一组token无效来实现用户退出登录。

基于token身份认证的完整实例相关推荐

  1. 【java】基于JWT的token身份认证方案

    1.概述 转载:基于JWT的token身份认证方案 2.使用JSON Web Token的好处 2.1 性能问题 验证信息可以由前端保存,后端不需要为保存token消耗内存.JWT方式将用户状态分散到 ...

  2. 使用 AngularJS NodeJS 实现基于token 的认证应用(转)

    认证是任何 web 应用中不可或缺的一部分.在这个教程中,我们会讨论基于 token 的认证系统以及它和传统的登录系统的不同.这篇教程的末尾,你会看到一个使用 AngularJS 和 NodeJS 构 ...

  3. java基于token的认证,Java实现基于token认证

    随着互联网的不断发展,技术的迭代也非常之快.我们的用户认证也从刚开始的用户名密码转变到基于cookie的session认证,然而到了今天,这种认证已经不能满足与我们的业务需求了(分布式,微服务).我们 ...

  4. WebApi后端框架Token身份认证,Api接口Token验证

    令牌概述(Token) 在以用户账号体系作为安全认证的信息系统中,对用户身份的鉴定是非常重要的事情. 令牌机制是软件系统安全体系中非常重要的部分,在计算机身份认证中是令牌的意思,一般作为邀请.登录以及 ...

  5. 分布式认证方案-基于token的认证方式

    基于token的认证方式,服务端不用存储认证数据,易维护扩展性强, 客户端可以把token 存在任意地方,并且可以实现web和app统一认证机制.其缺点也很明显,token由于自包含信息,因此一般数据 ...

  6. 何为 Token?什么是基于 token 的认证?

    何为 Token? token 其实就是一个令牌,一个 token 其实就是服务器生成的一段数据,包含了唯一性识别一个用户的信息,一般被生成为一长串随机字符和数字. 什么是基于 token 的认证? ...

  7. Springboot整合shiro基于url身份认证和授权认证

    你还不会shiro吗? 前奏 shiro核心配置文件(rolesFilter可选). 身份认证 多表登录源如何操作? 授权管理 如何解决界面多角色/资源问题 访问效果 权限管理在日常开发中很重要,所以 ...

  8. mysql url认证_Springboot+shiro基于url身份认证和授权认证

    你还不会shiro吗?前奏 shiro核心配置文件(rolesFilter可选). 身份认证 多表登录源如何操作? 授权管理 如何解决界面多角色/资源问题 访问效果 权限管理在日常开发中很重要,所以硬 ...

  9. java token身份认证_java – 基于Spring Security Token的身份验证

    以下是我能够实现基于令牌的身份验证和基本身份验证的方法 SpringSecurityConfig.java @Configuration @EnableWebSecurity public class ...

最新文章

  1. mysql load data on duplicate_带有ON DUPLICATE KEY UPDATE的MySQL LOAD DATA INFILE
  2. 编写python脚本完成图片拼接
  3. 征战蓝桥 —— 2016年第七届 —— C/C++A组第3题——方格填数
  4. Android传感器编程入门
  5. SYSTEM32 下的几乎所有文件的简单说明
  6. 力扣347. 前 K 个高频元素(JavaScript,堆)
  7. SQL Sever select定制查询
  8. 基于迁移学习的mini-imagenet数据分类实践
  9. 服务器PHPWAMP_IN2安装redis
  10. 2014第六届云计算大会参会体会和个…
  11. CentOS7.6腾讯云中域名的备案详细流程
  12. win7旗舰版 OEM KEY
  13. linux安装perf工具
  14. c轴 t轴 l轴_数控加工中心3轴、3+2轴、5轴加工的区别是什么?
  15. Unity—手机端的触屏控制
  16. 火焰特性识别的Matlab实现方法
  17. java rgb cmyk_Java CMYK图片转RGB图片(TwelveMonkeys方式)
  18. 对抗机器学习系列——深度神经网络的盲点
  19. 集成交互式道路与立交设计系统 EICAD
  20. c语言中len的作用,C语言 int len( )  求大神解释

热门文章

  1. 手机火狐浏览器怎么开启flash_如何开启Firefox浏览器flash支持?开启Firefox浏览器flash支持的方法...
  2. nodejs使用xlsx和xlsx-style导出Excel文件
  3. 遇到电脑打字没有候选字框解决办法
  4. 第二类Stirling数(第二类斯特林数)
  5. 云扩科技与帆软软件达成战略合作,携手共建RPA+BI新生态
  6. 帆软单点登录_帆软单点登陆
  7. c语言计算支点距离,长安本科毕业论文设计-—三级齿轮减速器的优化设计(附c语言优化计算程序代码).doc...
  8. rst 语法+简明教程
  9. 硝烟弥漫 三大运营商开启新一轮宽带市场争夺赛
  10. 计算几何----极角排序