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

一、参数格式

二、后端实现

复制代码
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进行访问
相关推荐
_周游2 分钟前
Java8 API 文档搜索引擎_2.索引模块(实现细节)
java·搜索引擎·intellij-idea
鱼跃鹰飞2 分钟前
大厂面试真题-说说Kafka消息的不重复和不丢失
java·分布式·kafka
A懿轩A3 分钟前
【Maven 构建工具】Maven 依赖管理详解:坐标、传递、作用域与依赖冲突解决(一篇搞懂)
java·linux·maven
2601_949543013 分钟前
Flutter for OpenHarmony垃圾分类指南App实战:资讯详情实现
android·java·flutter
cyforkk2 小时前
12、Java 基础硬核复习:集合框架(数据容器)的核心逻辑与面试考点
java·开发语言·面试
身如柳絮随风扬7 小时前
Java中的CAS机制详解
java·开发语言
风筝在晴天搁浅8 小时前
hot100 78.子集
java·算法
故事和你919 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口
Configure-Handler10 小时前
buildroot System configuration
java·服务器·数据库
:Concerto10 小时前
JavaSE 注解
java·开发语言·sprint