springsecurity-oauth2集成,jwt生成token,源码解析

springsecurity-oauth2集成,jwt生成token

1. SpringSecurity

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是保护基于spring的应用程序的事实标准。

提供认证、授权和常见的攻击防护的功能。是Spring提供的安全框架。

Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.

2. OAuth2

OAuth(Open Authorization)开放授权是为用户资源的授权定义一个安全、开放的标准。而OAuth2是OAuth协议的第二个版本。OAuth常用于第三方应用授权登录。在第三方无需知道用户账号密码的情况下,获取用户的授权信息。常见的授权模式有:授权码模式、简化模式、密码模式和客户端模式。

认证配置:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

	@Autowired
	private DataSource dataSource;

	@Autowired
	private JwtAccessTokenConverter jwtAccessTokenConverter;
	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	private ClientDetailsService clientDetails;
	
	@Autowired
	private UserDetailsService userDetailsService;

	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		//配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services)
		endpoints.authenticationManager(this.authenticationManager);
		
		endpoints.setClientDetailsService(clientDetails);
		endpoints.userDetailsService(userDetailsService);
//		endpoints.tokenServices(tokenServices());
		endpoints.tokenStore(tokenStore());
		endpoints.accessTokenConverter(jwtAccessTokenConverter);
//		endpoints.exceptionTranslator(new MyWebResponseExceptionTranslator());
//		endpoints.authenticationManager(authenticationManager)

	}
	
	@Override
	public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {//配置令牌端点(Token Endpoint)的安全约束
		oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
		  oauthServer.allowFormAuthenticationForClients();
	}

	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		//配置客户端详情,与持久化信息联用
		clients.jdbc(dataSource);
	}

	/**
	 * redis token 配置
	 */
	//@Bean
//	public TokenStore redisTokenStore() {
//		return new RedisTokenStore(redisConnectionFactory);
//	}

	@Bean // 声明 ClientDetails实现
	public ClientDetailsService clientDetails() {
		return new JdbcClientDetailsService(dataSource);
	}

	@Bean
	public TokenStore tokenStore() {
//	    return new InMemoryTokenStore();
		return new JdbcTokenStore(dataSource);
	}

	@Bean
    public TokenEnhancer jwtTokenEnhancer(){
        return new JwtTokenEnhancer();
    }
}
@Slf4j
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);

    private static final String NAME_AND_SALT ="123";

    @Bean
    public static NoOpPasswordEncoder passwordEncoder() {
        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setHideUserNotFoundExceptions(false);
        provider.setUserDetailsService(userDetailsService());
        provider.setPasswordEncoder(passwordEncoder());
        return provider;
    }

    @Autowired
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
        //配置用户来源于数据库
        auth.userDetailsService(userDetailsService()).passwordEncoder(new org.springframework.security.crypto.password.PasswordEncoder() {
            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                // 无需验证密码
                if ("no_pass".equals(rawPassword)) {
                    return true;
                }
                if (encodedPassword != null) {
                    String passwordEn = encodedPassword.substring(0, 32);
//                    String nameAndsalt = encodedPassword.substring(32);
                    return MD5Encrypt.encrypt(rawPassword + NAME_AND_SALT).equals(passwordEn);
                }
                return false;
            }

            @Override
            public String encode(CharSequence rawPassword) {
                return rawPassword.toString();
            }
        });
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        // 忽略所有管理监控地址
        web.ignoring().antMatchers("/actuator/**");
        web.ignoring().antMatchers("/logout");
        web.ignoring().antMatchers("/verify");
        web.ignoring().antMatchers("/jwt/check");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //basic 登录方式
        http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll().anyRequest().authenticated()
                .and()
                .httpBasic().disable().csrf().disable();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    @Bean
    public UserDetailsService userDetailsService() {
        UserDetailsService userDetailsService = new UserDetailsService(){
            @Override
            public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
                // 固定密码,后续这块可以改为自有项目的user信息模块
                String password = "123456";
                password = MD5Encrypt.encrypt(password + NAME_AND_SALT);
//                password = password + userName + NAME_AND_SALT;
                UserDetails userDetails = new User(userName, password, AuthorityUtils.createAuthorityList(new String[]{"ROLE_ANONYMOUS"}));

                return userDetails;
            }
        };

        return userDetailsService;
    }
}

 

 

本地部署调试

环境准备:mysql5+,jdk8+

  • 1.先执行sql语句,oauth2使用的表;
  • 2.目前支持password+jwt生成token;
  • 3.可以反解析jwt内容;
  • 4.获取token:http://127.0.0.1:8601/oauth/token?username=user1&password=123456&type=password&client_id=test&client_secret=test1234&grant_type=password
  • 5.反解析token:http://127.0.0.1:8601/jwt/check ; header配置Content-Type:application/json; Authorization:上一步获取的access_token值

源码路径:https://github.com/MrZhengliang/springsecurity-oauth2

本地可直接运行测试。

你可能感兴趣的:(源码研究,springboot,框架)