spring-security-oauth2(十九) 重构用户名密码登陆

在开始重构前我们来回忆下前面的流程

三种方式登陆成功后组装后续流程返回token,必须携带basic client信息(因为需要它获取clientDetails信息)

 

 

 ok分析完流程后我们进行重构。先直接用浏览器的配置进行修改后续继续重构优化

登陆成功转换token处理

package com.rui.tiger.auth.core.authentication;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rui.tiger.auth.core.model.enums.LoginTypeEnum;
import com.rui.tiger.auth.core.properties.SecurityProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.config.annotation.configuration.ClientDetailsServiceConfiguration;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Base64;

/**
 * 认证成功处理器
 * {@link SavedRequestAwareAuthenticationSuccessHandler}是Spring Security默认的成功处理器
 *
 * @author CaiRui
 * @date 2018-12-6 12:39
 */
@Component("tigerAuthenticationSuccessHandler")
@Slf4j
public class TigerAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

	@Autowired
	private SecurityProperties securityProperties;
	/**
	 * 授权服务器:自动配置的
	 * @see ClientDetailsServiceConfiguration#clientDetailsService()
	 */
	@Autowired
	private ClientDetailsService clientDetailsService;
	@Autowired
	private AuthorizationServerTokenServices authorizationServerTokenServices;
	@Autowired
	private ObjectMapper objectMapper;

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
		log.info("登录成功");
		/**
		 * @see BasicAuthenticationFilter#doFilterInternal(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain)
		 *  */
		String header = request.getHeader("Authorization");
		if (header == null || !header.startsWith("Basic ")) {
			// 不被认可的客户端异常
			throw new UnapprovedClientAuthenticationException("没有Authorization请求头");
		}
		// 解析请Authorization 获取client信息 client-id: tigerauth client-secret: 123456
		String[] tokens = extractAndDecodeHeader(header, request);
		assert tokens.length == 2;
		String clientId = tokens[0];
		String clientSecret = tokens[1];
		ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
		// 判定提交的是否与查询的匹配
		if (clientDetails == null) {
			throw new UnapprovedClientAuthenticationException("clientId对应的配置信息不存在:" + clientId);
		} else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {
			throw new UnapprovedClientAuthenticationException("clientSecret不匹配:" + clientId);
		}
		/**  @see DefaultOAuth2RequestFactory#createTokenRequest(java.util.Map, org.springframework.security.oauth2.provider.ClientDetails)
		 * requestParameters,不同的授权模式有不同的参数,这里自定义的模式,没有参数
		 * String clientId,
		 * Collection<String> scope, 给自己的前段使用,默认用所有的即可
		 * String grantType 自定义 custom
		 * */
		TokenRequest tokenRequest = new TokenRequest(MapUtils.EMPTY_SORTED_MAP, clientId, clientDetails.getScope(), "custom");
		OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
		/**
		 * @see org.springframework.security.oauth2.provider.token.AbstractTokenGranter#getOAuth2Authentication(org.springframework.security.oauth2.provider.ClientDetails, org.springframework.security.oauth2.provider.TokenRequest)
		 * */
		OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
		OAuth2AccessToken accessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
		response.setContentType("application/json;charset=UTF-8");
	/*	log.info("TOKEN信息:" + JSON.toJSONString(accessToken));
		response.getWriter().write(JSON.toJSONString(accessToken));*/
		log.info("jack TOKEN信息:" + objectMapper.writeValueAsString(accessToken));
		response.getWriter().write(objectMapper.writeValueAsString(accessToken));
	}

	/**
	 * Decodes the header into a username and password.
	 * @throws BadCredentialsException if the Basic header is not present or is not valid
	 *                                 Base64
	 */
	private String[] extractAndDecodeHeader(String header, HttpServletRequest request) throws IOException {
		byte[] base64Token = header.substring(6).getBytes("UTF-8");
		byte[] decoded;
		try {
			decoded = Base64.getDecoder().decode(base64Token);
		} catch (IllegalArgumentException e) {
			throw new BadCredentialsException(
					"Failed to decode basic authentication token");
		}
		String token = new String(decoded, "UTF-8");
		int delim = token.indexOf(":");
		if (delim == -1) {
			throw new BadCredentialsException("Invalid basic authentication token");
		}
		return new String[]{token.substring(0, delim), token.substring(delim + 1)};
	}

}

权限配置器

package com.rui.tiger.auth.app;

import com.rui.tiger.auth.core.config.CaptchaSecurityConfig;
import com.rui.tiger.auth.core.config.SmsAuthenticationSecurityConfig;
import com.rui.tiger.auth.core.properties.SecurityConstants;
import com.rui.tiger.auth.core.properties.SecurityProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.social.security.SpringSocialConfigurer;

/**
 * @author CaiRui
 * @date 2019-04-17 08:38
 */
@Configuration
@EnableResourceServer
public class TigerResourceServerConfig extends ResourceServerConfigurerAdapter{

    @Autowired
    private AuthenticationSuccessHandler tigerAuthenticationSuccessHandler;
    @Autowired
    private AuthenticationFailureHandler tigerAuthenticationFailureHandler;

    @Autowired
    private SmsAuthenticationSecurityConfig smsAuthenticationSecurityConfig;//短信登陆配置
    @Autowired
    private SpringSocialConfigurer tigerSpringSocialConfigurer;

    @Autowired
    private SecurityProperties securityProperties;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        /**
         * 表单密码配置
         */
        http.formLogin()
                .loginPage(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL)
                .loginProcessingUrl(SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_FORM)//
                .defaultSuccessUrl("/index.html")
                .successHandler(tigerAuthenticationSuccessHandler)
                .failureHandler(tigerAuthenticationFailureHandler);

        http
                /*.apply(captchaSecurityConfig) //图形验证码的有问题 先不处理
                .and()*/
                .apply(smsAuthenticationSecurityConfig)
                .and()
                .apply(tigerSpringSocialConfigurer)
                .and()
                .authorizeRequests()
                .antMatchers(
                        SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,//权限认证
                        SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_MOBILE,//手机
                        securityProperties.getBrowser().getLoginPage(),//登录页面
                        SecurityConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX+"/*",//  /captcha/* 验证码放行
                        securityProperties.getBrowser().getSignupUrl(),
                        //这个第三方自定义权限 后续抽离出去 可配置
                        securityProperties.getBrowser().getLoginOut(),
                        "/user/regist",
                        "/index.html",
                        securityProperties.getBrowser().getSession().getInvalidSessionUrl())
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf().disable();
    }
}

ok 我们来测试下

 带上token访问用户信息

ok 下章我们 重构短信登陆。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值