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
本地可直接运行测试。