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

一、参数格式

二、后端实现

复制代码
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进行访问
相关推荐
小小寂寞的城1 小时前
JAVA观察者模式demo【设计模式系列】
java·观察者模式·设计模式
探索java1 小时前
Java并发编程中的StampedLock详解:原理、实践与性能优化
java·stampedlock
界面开发小八哥2 小时前
「Java EE开发指南」如何用MyEclipse将Java项目转换为Web项目?
java·ide·java-ee·eclipse·开发工具·myeclipse
pobu1682 小时前
aksk前端签名实现
java·前端·javascript
一个天蝎座 白勺 程序猿2 小时前
飞算JavaAI进阶:重塑Java开发范式的AI革命
java·开发语言·人工智能
前端 贾公子2 小时前
tailwindCSS === 使用插件自动类名排序
java·开发语言
没有bug.的程序员2 小时前
JAVA面试宝典 -《Spring Boot 自动配置魔法解密》
java·spring boot·面试
hnlucky3 小时前
《Nginx + 双Tomcat实战:域名解析、静态服务与反向代理、负载均衡全指南》
java·linux·服务器·前端·nginx·tomcat·web
hnlucky3 小时前
同时部署两个不同版本的tomcat要如何配置环境变量
java·服务器·http·tomcat·web