一、参数格式
二、后端实现
Controller层
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
@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
-
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
-
@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进行访问