iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >若依前后端分离版:增加新的登录接口,用于小程序或者APP获取token,并使用若依的验证方法
  • 554
分享到

若依前后端分离版:增加新的登录接口,用于小程序或者APP获取token,并使用若依的验证方法

小程序前端 2023-09-23 16:09:31 554人浏览 安东尼
摘要

LoginController类 具体代码 @AnonymousAccess @PostMapping("login") public ajaxResult login(@RequestBody LoginBody

LoginController类

具体代码 
    @AnonymousAccess    @PostMapping("login")    public ajaxResult login(@RequestBody LoginBody loginBody) {        AjaxResult ajax = AjaxResult.success();        // 生成令牌        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword());        ajax.put(Constants.TOKEN, token);        return ajax;    }

登录校验 ——AppLoginService类

 具体代码

@Resourceprivate AppAuthenticationProvider authenticationManager;      public String login(String username, String passWord) {        // 用户验证        Authentication authentication;        try {            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername            authentication = authenticationManager                    .authenticate(new UsernamePasswordAuthenticationToken(username, password));        } catch (Exception e) {            if (e instanceof BadCredentialsException) {                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));                throw new UserPasswordNotMatchException();            } else {                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));                throw new ServiceException(e.getMessage());            }        }        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));        LoginUser loginUser = (LoginUser) authentication.getPrincipal();        recordLoginInfo(loginUser.getUserId());        // 生成token        return tokenService.createToken(loginUser);    }
AppAuthenticationProvider 类

 具体代码

@Componentpublic class AppAuthenticationProvider implements AuthenticationProvider {    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);    @Autowired    private AppUserDetailsServiceImpl userDetailsService;    @SneakyThrows    @Override    public Authentication authenticate(Authentication authentication) throws AuthenticationException {        String userName = authentication.getName();// 这个获取表单输入中返回的用户名;        Object password = authentication.getCredentials();//这个获取表单输入中返回的密码;        // 这里构建来判断用户是否存在和密码是否正确        UserDetails userInfo = userDetailsService.loadUserByUsername(userName); // 这里调用我们的自己写的获取用户的方法;        if(!SecurityUtils.matchesPassword(password.toString(),userInfo.getPassword())){            log.info("用户不存在/密码错误,{}", userName);            throw new ServiceException("用户不存在/密码错误");        }                Collection authorities = userInfo.getAuthorities();        // 构建返回的用户登录成功的token        return new UsernamePasswordAuthenticationToken(userInfo, userInfo.getPassword(), authorities);    }    @Override    public boolean supports(Class authentication) {//        return authentication.equals(UsernamePasswordAuthenticationToken.class);        // 这里直接改成 return true;表示是支持这个执行        return true;    }}
AppUserDetailsServiceImpl类

 具体代码

@Servicepublic class AppUserDetailsServiceImpl implements UserDetailsService {    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);    @Autowired    private IProductMemberService memberService;//自己写的接口    @Autowired    private IProductMemberCourtService memberCourtService;    @Override    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {        ProductMember member = memberService.selectUserByUserName(username);//验证登录用户        if (StringUtils.isNull(member)) {            log.info("登录用户:{} 不存在.", username);            throw new ServiceException("登录用户:" + username + " 不存在");        } else if (UserStatus.DELETED.getCode().equals(member.getDelFlag())) {            log.info("登录用户:{} 已被删除.", username);            throw new ServiceException("对不起,您的账号:" + username + " 已被删除");        } else if (UserStatus.DISABLE.getCode().equals(member.getStatus())) {            log.info("登录用户:{} 已被停用.", username);            throw new ServiceException("对不起,您的账号:" + username + " 已停用");        }        return createLoginUser(member);    }    public UserDetails createLoginUser(ProductMember member) {        return new LoginUser(member.getMemberId(), memberCourtService.selectCourtIdByMemberId(member.getMemberId()), member);    }}

此时运行时,会有冲突!!!

需要在 xxx-framework/src/main/java/....../SecurityConfig中条件

    @Qualifier("userDetailsServiceImpl")

如图:

 此时启动项目不会报冲突的错

千万千万要添加!!!

下图中的LongUser类要添加东西

 要在public String getPassword(){}中添加自己写的登录实体类的getPassword()

以上内容已经可以解决app和小程序新的登录接口方案和后台管理的登陆获取token不冲突

以下内容可作为参考:

登录认证Jwttoken验证机制

后端部分
/login 接口
userName
password
code 验证码
前端获取上面三个要素后调用接口,整体改接口做了下面几件事情

验证用户身份(账号密码+验证码)
2、生成token
3、保存用户登录态到spring security中

安全配置:定义了基本的配置信息framework.config.SecurityConfigUserDetailsServiceImpl 用户验证处理类登录接口的服务类framework.WEB.service.SysLoginServiceJWT拦截器,拦截令牌并校验信息framework.security.filter.JwtAuthenticationTokenFilter


详细过程

SysLoginService 中调用UserDetailsServiceImpl校验用户的密码是否匹配以及用户账户状态,校验通过后返回UserDetails实例,该实例包含了用户的基本信息和菜单权限信息
2、调用tokenService.createToken(loginUser)生成token
令牌生成的详细过程

生成uuid随机数,这个随机数用来做Rediskey存储token
生成一个token(无时效)
拦截到的token如果距离失效在10分钟以内(可配置)就自动刷新有效期

前面提到了token本身无时效,有效期是通过redis控制的,因为jwt本身未提供刷新有效期的方法(可能是我不知道)。

以上用户调用了login接口并且获得了token

jwt令牌校验
 

@Componentpublic class JwtAuthenticationTokenFilter extends OncePerRequestFilter{    @Autowired    private TokenService tokenService;    @Override    protected void doFilterInternal(httpservletRequest request, HttpServletResponse response, FilterChain chain)            throws ServletException, IOException    {        LoginUser loginUser = tokenService.getLoginUser(request);        if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))        {            tokenService.verifyToken(loginUser);            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));            SecurityContextHolder.getContext().setAuthentication(authenticationToken);        }        chain.doFilter(request, response);    }}


代码比较短,所以就直接贴出来,这段代码拦截了所有请求并且完成了令牌的校验和刷新,具体过程如下

tokenService.getLoginUser(request); 从request中获取token并校验,如果校验通过就返回LoginUser对象
2、校验LoginUser的token,如果再刷限期内就直接刷新
3、将LoginUser封装到SecurityContextHolder中作为全局的用户登录状态


注:第3条有两个好处

后续拦截器发现SecurityContextHolder中保存了用户时,就直接通过校验
2、通过SecurityContextHolder可以快速获取当前请求的登录信息。
以上基本上已经说名了JWT校验的基本过程,忽略了很多细节

getInfo 获取用户信息
1、用户的基本信息
2、用户所有的Permissions(菜单树)
3、用户所有的RopePersmission(roleKeys)

在这里插入图片描述
getRouters 获取前端页面路由信息
这个接口完全为前端准备,后面会专门讲述前端的权限控制

 在这里插入图片描述

来源地址:https://blog.csdn.net/yyongsheng/article/details/127584458

--结束END--

本文标题: 若依前后端分离版:增加新的登录接口,用于小程序或者APP获取token,并使用若依的验证方法

本文链接: https://www.lsjlt.com/news/416549.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作