spring cloud oauth2 替换用户信息

在spring cloud 的oauth2认证中,有一个用户认证服务auth,提供客户端的认证,由于oauth2有多种授权方式,不同的授权采用的方式就不一样了。

在实际业务中,比如有个应用A,有自己的数据库A,需要auth授权后才能登陆,PC端登录的时候采用的是授权码模式,使用 @EnableOAuth2Sso 注解标记一个 WebSecurityConfigurerAdapter 类。当登录认证成功后会广播一个event事件,这个事件可以监听到,所以我们采用的是监听InteractiveAuthenticationSuccessEvent事件,这个是通过自动交互的手段来登录成功,比如cookie自动登录。具体实现细节如下,实际应用采用的是注释掉的代码,两种都可以参考:

   @EventListener
    public void authSuccessListener(InteractiveAuthenticationSuccessEvent event){
        System.out.println("哎呦喂,登录成功了");
        Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
        //通用替换,针对用户名密码登录的
        if(authentication instanceof UsernamePasswordAuthenticationToken){
            UsernamePasswordAuthenticationToken originToken= (UsernamePasswordAuthenticationToken) authentication;
            String username= originToken.getName();
            System.out.println(username);
            //查找用户,这里直接模拟查到了用户,根据需求进行替换
            Person person=new Person(username,20);
            UsernamePasswordAuthenticationToken token=new UsernamePasswordAuthenticationToken(originToken.getPrincipal(),"N/A",originToken.getAuthorities());
            token.setDetails(person);
            SecurityContextHolder.getContext().setAuthentication(token);
        }
        //auth2替换
        //替换oauth认证的信息里的details,这里就不展示了
       /* if (authentication instanceof OAuth2Authentication) {
            OAuth2Authentication originalOAuth2Authentication = (OAuth2Authentication) authentication;
            if (!originalOAuth2Authentication.isClientOnly()) {
                Authentication userAuthentication = originalOAuth2Authentication.getUserAuthentication();
                if (userAuthentication instanceof UsernamePasswordAuthenticationToken) {
                    UsernamePasswordAuthenticationToken originalUsernamePasswordAuthentication = (UsernamePasswordAuthenticationToken) userAuthentication;

                    String username = (String) originalUsernamePasswordAuthentication.getPrincipal();
                    //可以根据username查找用户,这里模拟获取用户
                    Person person=new Person("二狗子",18);
                    if (person != null) {
                        //替换用户信息,权限信息根据自己的需求替换,这里直接取原来的
                        UsernamePasswordAuthenticationToken usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(originalUsernamePasswordAuthentication.getPrincipal(), "N/A", originalUsernamePasswordAuthentication.getAuthorities());
                        usernamePasswordAuthentication.setDetails(person);

                        OAuth2Authentication oauth2Authentication = new OAuth2Authentication(originalOAuth2Authentication.getOAuth2Request(), usernamePasswordAuthentication);
                        oauth2Authentication.setDetails(originalOAuth2Authentication.getDetails());

                        SecurityContextHolder.getContext().setAuthentication(oauth2Authentication);
                    }
                }
            }
        }*/
    }

但是在APP登录的时候采用的授权方式是密码,这样认证的时候是根据认证token,只是一个token没有像pc端那样有cookie去自动验证,服务器是通过资源服务器认证的,只要token通过就可以访问被资源服务器保护的资源,这里都是/api/的接口。这种情况下就不能监听登录事件了,要在每次验证通过后去替换oauthAuthentication里面的details了,这样接口获取本应用当前登录用户的时候就可以直接获取了。那么如何实现认证成功后替换呢,根据spring security的尿性,增加一个filter,在最后一个filter之前替换。

@Component
public class CustomerSecurityFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("哎呦呵,来啦");
        //替换用户信息,具体替换步骤参考上一个替换,这个用户最好存入缓存,毕竟过滤器过滤的请求挺多,每次都要查询很坑的
        filterChain.doFilter(servletRequest,servletResponse);
    }
}
 @Autowired
    private CustomerSecurityFilter customerSecurityFilter;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/","/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/chat")
                .permitAll()
                .and()
                .logout()
                .permitAll()
                .and()
                .addFilterBefore(customerSecurityFilter,SwitchUserFilter.class);
    }


猜你喜欢

转载自blog.csdn.net/qq_28056641/article/details/80753760
今日推荐