Spring Security OAuth2+CAS(添加cas模式)

导读:本篇文章讲解 Spring Security OAuth2+CAS(添加cas模式),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

前言

Spring Security OAuth2 自带有4中模式,有些特殊情况是需要自定义。(本文的前提是需要知道如何添加自定义的模式)
现在的需求是现有的Spring Security OAuth2的认证对接cas认证中心。

maven

		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-cas</artifactId>
			<version>5.0.6.RELEASE</version>
		</dependency>

添加CasTicketTokenGranter

这里的grant_type 就是这里定义的cas_ticket

public class CasTicketTokenGranter extends AbstractTokenGranter {

    private static final String GRANT_TYPE = "cas_ticket";

    private final AuthenticationManager authenticationManager;

    public CasTicketTokenGranter(AuthenticationManager authenticationManager,
                                 AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) {
        this(authenticationManager, tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
    }

    protected CasTicketTokenGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices,
                                    ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) {
        super(tokenServices, clientDetailsService, requestFactory, grantType);
        this.authenticationManager = authenticationManager;
    }

    @Override
    public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
        OAuth2AccessToken token = super.grant(grantType, tokenRequest);
        if (token != null) {
            DefaultOAuth2AccessToken norefresh = new DefaultOAuth2AccessToken(token);
            // The spec says that cas ticket should not be allowed to get a refresh token
            norefresh.setRefreshToken(null);
            token = norefresh;
        }
        return token;
    }

    @Override
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {

        Map<String, String> parameters = new LinkedHashMap<String, String>(tokenRequest.getRequestParameters());
        String username = CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER;
        String password = parameters.get("ticket");

        if (password == null) {
            throw new InvalidRequestException("A cas ticket must be supplied.");
        }

        Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password);
        ((AbstractAuthenticationToken) userAuth).setDetails(parameters);
        try {
            userAuth = authenticationManager.authenticate(userAuth);
        }
        catch (AccountStatusException ase) {
            //covers expired, locked, disabled cases (mentioned in section 5.2, draft 31)
            throw new InvalidGrantException(ase.getMessage());
        }
        catch (BadCredentialsException e) {
            // If the ticket is wrong the spec says we should send 400/invalid grant
            throw new InvalidGrantException(e.getMessage());
        }
        if (userAuth == null || !userAuth.isAuthenticated()) {
            throw new InvalidGrantException("Could not authenticate ticket: " + password);
        }

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

tokenGranters中添加自定义的cas模式

注意看最下面

private List<TokenGranter> getDefaultTokenGranters() {
        AuthorizationServerTokenServices tokenServices = tokenServices();
        AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices();
        OAuth2RequestFactory requestFactory = requestFactory();

        List<TokenGranter> tokenGranters = new ArrayList<TokenGranter>();
        // 添加授权码模式
        tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetailsService, requestFactory));
        // 添加刷新令牌的模式
        tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetailsService, requestFactory));
        // 添加隐士授权模式
        tokenGranters.add(new ImplicitTokenGranter(tokenServices, clientDetailsService, requestFactory));
        // 添加客户端模式
        tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, requestFactory));
        if (authenticationManager != null) {
            // 添加密码模式
            tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory));
            // 添加自定义授权模式(手机号码)
            tokenGranters.add(new MobileCodeTokenGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory));
            // 添加自定义授权模式(cas)
            tokenGranters.add(new CasTicketTokenGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory));
        }
        return tokenGranters;
    }

添加CasAuthenticationProvider

注意cas携带的service地址要和 serviceProperties.setService()这里的地址一样

	public static String casServerUrlPrefix="http://127.0.0.1:8081/cas";
	@Bean("pgtStorage")
    public ProxyGrantingTicketStorageImpl proxyGrantingTicketStorageImpl(){
        return new ProxyGrantingTicketStorageImpl();
    }

    @Bean("casAuthenticationProvider")
    public CasAuthenticationProvider casAuthenticationProvider(){
        CasAuthenticationProvider authenticationProvider=new CasAuthenticationProvider();
        authenticationProvider.setKey("casProvider") ;
        authenticationProvider.setAuthenticationUserDetailsService(OauthCasService);
        Cas20ProxyTicketValidator ticketValidator=new Cas20ProxyTicketValidator(casServerUrlPrefix);
        ticketValidator.setAcceptAnyProxy(true);//允许所有代理回调链接
        ticketValidator.setProxyGrantingTicketStorage(proxyGrantingTicketStorageImpl());
        authenticationProvider.setTicketValidator(ticketValidator);
        authenticationProvider.setServiceProperties(serviceProperties());
        return authenticationProvider;
    }

    @Bean
    public ServiceProperties serviceProperties(){
        ServiceProperties serviceProperties=new ServiceProperties();
        serviceProperties.setService("http://127.0.0.1:8881/base/oauth/toke");
        serviceProperties.setAuthenticateAllArtifacts(true);
        return serviceProperties;
    }

AuthenticationManagerBuilder中添加Provider

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(casAuthenticationProvider()).userDetailsService(OauthUserService).passwordEncoder(passwordEncoder()).and().authenticationProvider(mobileAuthenticationProvider());
    }

OauthCasServiceImpl

@Service("OauthCasService")
public class OauthCasServiceImpl implements AuthenticationUserDetailsService<CasAssertionAuthenticationToken> {

	@Autowired
	private com.datanew.service.UserService UserService;

	@Override
	public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {
		String name = token.getName();
		System.out.println("获得的用户名:"+name);
		BaseOperator userinfo = UserService.getUserByUsername(name);
		if (userinfo==null){
			throw new UsernameNotFoundException(name+"不存在");
		}
		User user =  new User(name,userinfo.getPassword(), AuthorityUtils.createAuthorityList("ROLE_ADMIN"));
		return new OauthUser(userinfo,user);
	}
}

public interface OauthCasService extends UserDetailsService {

}

cas登录流程

需要cas认证中心支持restfult模式

  1. 客户端使用用户名密码获取TGT
  2. 使用TGT获取ticket
  3. 使用ticket获取access_token
  4. 一般来说需要自己封装一个接口获取token并把token设置到cookie中并重定向到前端项目

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/15305.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!