oauth2实现免登录(springSecurity)

代码怎么写,原理等请参考阮一峰博客
四种模式都讲的非常清楚,这里我就我遇到的问题做个记录
什么用户存入数据库,客户端信息持久化,access_token存入redis等问题网上都可以搜到

我所遇到的问题

  1. 在获取code的时候,也就是 /oauth/authorize 接口(在AuthorizationEndpoint类中)
    User must be authenticated with Spring Security before authorization can be completed.
    这是没有登陆的错误,springsecurity整合oauth2,必须要求用户登陆

解决方法:
a. 通过springSecurity中的form表单进行登陆后再进行请求(一般项目可能不需要登陆)
b. 如何实现免登录?
我们先来讲讲为什么需要登陆,当登陆之后,浏览器会保留一个sessionId,springSecurity也是通过这个来判断用户是否登陆,用户需要登陆才能访问被保护的资源

你在网上能够找到教程实现免登录:
在这里插入图片描述
确实是利用securityContextHolder进行操作(详细细节,自己看源码去或者百度去)

现在这里给出一个规范一点的实现流程:

@Slf4j
public class AuthenticationTokenFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        String account = httpServletRequest.getHeader("account");
        String credentials = httpServletRequest.getHeader("credentials");
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(account, credentials);
        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        filterChain.doFilter(httpServletRequest,httpServletResponse);
    }
}

最关键的是中间三行代码,account和credentials是我这边的业务需求,这两个字段就相当于username和password,给这用户代码授权登陆
然后将过滤器添加到webSecurityConfig(也就是你配置security的)
在UsernamePasswordAuthenticationFilter.class之前添加,这个addFilterBefore也可以换成addFilterAt

@Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)//禁止生成cookie
                .and().addFilterBefore(new AuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class)//免登录过滤器
                .authorizeRequests().antMatchers("/oauth/**","/login").permitAll()
                .and().formLogin().permitAll()
                .and().csrf().disable().httpBasic();
    }
  1. springSecurity如何禁用session/cookie,有些系统可能对安全性比较高(不能使用)
    解决方案见上面代码
    SessionCreationPolicy他有四个值,注意Never和STATELESS的区别

  2. 如何实现退出登陆,销毁access_token和refresh_token?
    我是将access_token 等信息保存在redis中,可以通过如下代码删除access_token

    @Autowired
    TokenStore tokenStore;
    @GetMapping(value = "/userLogout",name = "Nova退出")
    public void novaUserLogout(HttpServletRequest request){
        OAuth2AuthenticationDetails details = new OAuth2AuthenticationDetails(request);
        OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(details.getTokenValue());
        OAuth2RefreshToken oAuth2RefreshToken = tokenStore.readRefreshToken(oAuth2AccessToken.getRefreshToken().getValue());
        tokenStore.removeAccessToken(oAuth2AccessToken);
        tokenStore.removeRefreshToken(oAuth2RefreshToken);
    }
  1. 如何从access_token 中获取用户信息(也就是登陆的用户信息)
    说明: auth.getPrincipal()保存的就是用户登陆信息,我的用户是来自于数据库
    MyUserDetails这个是我登陆用户信息的封装
@GetMapping("/getUserInfo")
    public OauthUserInfoVO getUserInfo(Authentication auth){
        MyUserDetails principal = (MyUserDetails) auth.getPrincipal();
        //long userId = principal.getUser().getUserId();
       // OauthUserInfo oauthUserInfo = userMapper.selectOauthUserInfoById(userId);
        //OauthUserInfoVO oauthUserInfoVO = CopyUtils.copy(oauthUserInfo, OauthUserInfoVO.class);
        //return oauthUserInfoVO;
    }

大概就是这些问题,匆匆忙忙的记录一下,希望对读者有帮助

你可能感兴趣的:(springboot,oauth2)