oauth2自定义授权认证模式

不废话,直接上代码,具体实现“自定义授权”如下:
1、自定义授权码模式


import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 自定义授权码模式
 */
public class MyAbstractTokenGranter extends AbstractTokenGranter {

    //我们授权模式注册到oauth中的名称// 这里就是授权模式名
    private static final String GRANT_TYPE = "my_type";

    private AuthenticationManager authenticationManager;

    // 这里创建一个构造函数,配置的时候会用到
    public MyAbstractTokenGranter(AuthenticationManager authenticationManager
            , AuthorizationServerTokenServices tokenServices
            , ClientDetailsService clientDetailsService
            , OAuth2RequestFactory requestFactory) {
        super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
        this.authenticationManager = authenticationManager;
    }

    /*
     * 重写方法
     * @param client   客户端详细信息
     * @param tokenRequest  请求参数
     *
     */
    @Override
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
        // 这里将认证时的请求参数拿到
        Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
        //接收传入的参数
        String username = parameters.get("username");authenticationManager.authenticate(userAuth);

        // 这里是我们之前创建的授权前的构造函数,把参数传进去
        Authentication userAuth = new MyAbstractAuthenticationToken(username); // 未认证状态
        ((AbstractAuthenticationToken) userAuth).setDetails(parameters);

        // 对参数进行认证
        try {
            userAuth = this.authenticationManager.authenticate(userAuth); // 认证中
        } catch (Exception e) {
            throw new InvalidGrantException(e.getMessage());
        }

        // 判断时候认证成功
        if (userAuth == null || !userAuth.isAuthenticated()) {
            throw new InvalidGrantException("Could not authenticate group company token: " + username);
        }

        OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
        return new OAuth2Authentication(storedOAuth2Request, userAuth);
    }
}

2、自定义身份授权的Token
 


import java.util.Collection;

/**
 * 自定义身份授权令牌
 */
public class MyAbstractAuthenticationToken extends AbstractAuthenticationToken {
    //我也不知道这个是干嘛用的,反正必须要有
    private final Object principal;

    /** 认证未通过时的初始化方法 */
    public MyAbstractAuthenticationToken(String token){
        super(null);
        this.principal = token;
        setAuthenticated(false);
    }

    /** 认证通过后的初始化方法 */
    public MyAbstractAuthenticationToken(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) {
        if (isAuthenticated) {
            throw new IllegalArgumentException(
                    "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
        }
        super.setAuthenticated(false);
    }
}

3、自定义身份验证

我们可以通过配置类覆盖TokenGranter,在里面注入我们自定义的授权模式!

  • ProviderManager#authenticate(Authentication authentication)这个类是提供了认证的实现逻辑和流程,他负责从所有的AuthenticationProvider中找出具体的Provider进行认证


/**
 * 自定义身份验证
 */
@Configuration
@RequiredArgsConstructor
public class MyAuthenticationProvider implements AuthenticationProvider {

    private final UserFeignService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) {
        MyAbstractAuthenticationToken myAuthenticationToken = (MyAbstractAuthenticationToken) authentication;
        String userName = (String) myAuthenticationToken.getPrincipal();
        UserDetails user = userDetailsService.loadUserByUsername(userName);        

        MyAbstractAuthenticationToken authenticationToken = new MyAbstractAuthenticationToken(userName, user.getAuthorities());

        authenticationToken.setDetails(myAuthenticationToken.getDetails());
        return authenticationToken;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return MyAbstractAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

4、认证服务配置中增加自定义的授权

在继承AuthorizationServerConfigurerAdapter的配置类中添加如下代码

    /**
     * @param endpoints
     * @return
     */
    @Override
    public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // 获取原有默认授权模式(授权码模式、密码模式、客户端模式、简化模式)的授权者
        List<TokenGranter> granterList = new ArrayList<>(Arrays.asList(endpoints.getTokenGranter()));
        // 添加自定义授权模式授权者
        granterList.add(new MyAbstractTokenGranter(authenticationManager, endpoints.getTokenServices(),
                endpoints.getClientDetailsService(),
                endpoints.getOAuth2RequestFactory()
                ));
        CompositeTokenGranter compositeTokenGranter = new CompositeTokenGranter(granterList);
 
        //配置存储令牌策略
        endpoints
                //添加自定义模式
                .tokenGranter(tokenGranter(endpoints))
    }

    /**
     * 添加自定义授权类型
     *
     * @return List<TokenGranter>
     */
    private TokenGranter tokenGranter(AuthorizationServerEndpointsConfigurer endpoints) {
        // endpoints.getTokenGranter() 获取SpringSecurity OAuth2.0 现有的授权类型
        List<TokenGranter> granters = new ArrayList<TokenGranter>(Collections.singletonList(endpoints.getTokenGranter()));

        // 构建自定义授权类型
        MyTokenGranter smsCodeTokenGranter = new MyTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(),
                endpoints.getOAuth2RequestFactory(), myUserDetailsServiceImpl, authenticationManager);
        // 向集合中添加定义授权类型
        granters.add(smsCodeTokenGranter);
        // 返回所有类型
        return new CompositeTokenGranter(granters);
    }
添加自定义的provider

在SecurityConfig中,初始化provider,代码如下:

@EnableWebSecurity
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;
 
    @Autowired
    private IUserService userService;
 
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //实例化provider,把需要的东西set进去
        MyAuthenticationProvider  provider = new MyAuthenticationProvider ();
        provider.setUserDetailsService(userDetailsService);
        auth.authenticationProvider(provider);
    }
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot是一个开箱即用的Java开发框架,而授权模式(Authorization Code Grant)是OAuth 2.0的一种授权方式。在授权模式中,客户端先将用户重定向到认证服务器,然后经过用户登录并确认授权后,认证服务器会生成授权码,客户端再将授权码发送给认证服务器以获取访问令牌。 在Spring Boot中实现授权模式自定义页面,可以按照以下步骤进行: 1. 创建自定义页面:首先,在Spring Boot项目的resources目录下创建一个public目录,并在该目录下创建一个login.html页面用于用户登录和授权确认。 2. 配置认证服务器:在Spring Boot项目的配置文件(如application.properties或application.yml)中配置认证服务器相关的属性,包括认证服务器的端口、重定向URL等。 3. 创建授权码端点:在Spring Boot项目中创建授权码端点,即用于接收并响应用户的授权请求。可以使用Spring Security和OAuth 2.0的相关类和注解来实现授权码端点的功能。 4. 自定义登录和授权页面:在授权码端点的处理方法中,根据用户的请求判断是否需要展示登录页面或授权确认页面。如果需要展示页面,则返回自定义的login.html页面。 5. 处理用户登录和授权:在登录页面中,用户输入登录信息后,通过表单提交到授权码端点的处理方法中进行验证。验证成功后,生成授权码并重定向到客户端指定的重定向URL。在授权确认页面中,用户确认授权后,同样生成授权码并重定向到客户端。 通过以上步骤,就可以在Spring Boot中实现授权模式自定义页面。根据实际需求,可以根据自己的业务逻辑对登录和授权页面进行自定义和美化,提升用户体验。同时,也需要注意安全性,避免出现安全漏洞。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值