根据用户名称实现单点登录

一、参数格式

二、后端实现

复制代码
Controller层
java 复制代码
public class IAccessTokenLoginController extends BaseController {


    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISingleTokenServiceImpl tokenService;

    /**
     * 登录方法
     *
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult singleLogin(@RequestBody LoginBody loginBody) {

        String accessToken = loginBody.getAccessToken();
        if (StringUtils.isNotEmpty(accessToken)) {
            String tokenNew = tokenService.singleLogin(accessToken);
            AjaxResult ajax = AjaxResult.success();
            ajax.put(Constants.TOKEN, tokenNew);
            return ajax;

        } else {
            return AjaxResult.error();
        }


    }
}
复制代码
注意:LoginBody新增变量accessToken
java 复制代码
@Service
public class ISingleTokenServiceImpl implements ISingleTokenService {
    @Autowired
    private TokenService tokenService;
    @Autowired
    private AuthenticationManager authenticationManager;


    public String singleLogin(String accessToken) {
        // 用户验证
        Authentication authentication = null;
        String username =accessToken;
        try
        {
//            username=parseAccessToken(accessToken);
//不用进行处置 直接传参
            authentication = authenticationManager
                    .authenticate(new IAuthenticationToken(username));
        }
        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();

        // 生成token
        return tokenService.createToken(loginUser);
    }

    public String parseAccessToken(String accessToken) {
        try {
            // 从 access token 中提取 payload
            Claims claims = Jwts.parser()
                    .parseClaimsJws(accessToken)
                    .getBody();

            // 获取 username
            String username = (String) claims.get("username");

            return username;
        } catch (Exception e) {
            System.out.println("无法解析 access token!" + e);
            return null;
        }
    }
  • 添加自定义IAuthenticationToken
java 复制代码
public class IAuthenticationToken extends AbstractAuthenticationToken {

    private final Object principal;

    public IAuthenticationToken(Object principal) {
        super(null);
        this.principal = principal;
        this.setAuthenticated(false);
    }

    public IAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        super.setAuthenticated(true);
    }

    @Override
    public Object getCredentials() {
        return null;
    }

    @Override
    public Object getPrincipal() {
        return this.principal;
    }

    @Override
    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
        if (isAuthenticated) {
            throw new IllegalArgumentException(
                    "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
        }

        super.setAuthenticated(false);
    }

    @Override
    public void eraseCredentials() {
        super.eraseCredentials();
    }

}

添加IAuthenticationProvider
*

java 复制代码
@Component
public class IAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        IAuthenticationToken authenticationToken = (IAuthenticationToken) authentication;

        String username = (String) authenticationToken.getPrincipal();
        UserDetails user = userDetailsService.loadUserByUsername(username);
        IAuthenticationToken result = new IAuthenticationToken(user, Collections.emptyList());
        /*
        Details 中包含了 ip地址、 sessionId 等等属性 也可以存储一些自己想要放进去的内容
        */
        result.setDetails(authenticationToken.getDetails());
        return result;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return IAuthenticationToken.class.isAssignableFrom(aClass);
    }
}

修改SecurityConfig 放行我们的请求登录路径 并把自定义认证加进来

.antMatchers("/hello","/single/login","/login", "/register", "/captchaImage").anonymous()

@Override

protected void configure(AuthenticationManagerBuilder auth) throws Exception

{

复制代码
auth.authenticationProvider(new CustomLoginAuthenticationProvider(userDetailsService));
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
auth.authenticationProvider(iAuthenticationProvider);

}

  • 前端根据后台返回的token进行访问
相关推荐
云和数据.ChenGuang10 小时前
Python 重写(Override)深度解析:从 MRO 到 super() 的完整机制
java·开发语言·人工智能·python·langchain·1024程序员节
摇滚侠10 小时前
《On Java 中文版 基础卷》阅读笔记 实现隐藏 12
java·数据库·笔记
silvamux_13 小时前
10款模型写种草笔记:可发布性、返工来源与成本数据缺口复盘
java·数据库·笔记
步行cgn14 小时前
StringHttpMessageConverter 详解:Spring MVC 中字符串读写的默认转换器
java·spring·mvc
摇滚侠14 小时前
《On Java 中文版 基础卷》阅读笔记 实现隐藏 11
java·笔记·python
小蒜学长14 小时前
基于Spring Boot+Vue3的在线医疗咨询系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·在线问诊·在线医疗咨询系统
Deng桑14 小时前
SpringAI写第一个Agent-把工单循环跑起来
java·agent·工具调用·spring ai
步行cgn16 小时前
@ResponseBody 详解:Spring MVC 中把返回值直接写入响应体
java·spring·mvc
jason成都17 小时前
RTKLIB 的 Java 移植版来了:rtklib-java v3.3.0 功能全景
java·gnss·rtklib·rtklib_java
LazyHunter917 小时前
JDK 28:Java 下一步方向解析与新特性展望
java·jdk