SpringBoot+SpringSecurity+oAuth2+Redis实现简单授权认证

tech2024-02-18  68

首先引入jar包:

接下来是application.yml配置:

oAuth配置:

package com.vevor.mall.auth.config; import com.vevor.mall.auth.constants.RedisConstant; import com.vevor.mall.auth.entity.AuthUserDetails; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator; import org.springframework.security.oauth2.provider.token.TokenEnhancer; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; /** * * @author lixinyu * @date 2020-08-31 * @description 授权服务器配置 */ @Configuration @EnableAuthorizationServer public class AuthenticationServerConfig extends AuthorizationServerConfigurerAdapter { private final DataSource dataSource; private final PasswordEncoder passwordEncoder; private final AuthenticationManager authenticationManager; private final UserDetailsService userDetailsService; private final LettuceConnectionFactory lettuceConnectionFactory; public AuthenticationServerConfig(AuthenticationManager authenticationManager, @Qualifier("userDetailsServiceImpl") UserDetailsService userDetailsService, DataSource dataSource, PasswordEncoder passwordEncoder, LettuceConnectionFactory lettuceConnectionFactory) { this.authenticationManager = authenticationManager; this.dataSource = dataSource; this.userDetailsService = userDetailsService; this.passwordEncoder = passwordEncoder; this.lettuceConnectionFactory=lettuceConnectionFactory; } /** * 第三方客户端信息配置 * @param clients 定义客户端详细信息服务的配置程序 * @throws Exception */ @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { super.configure(clients); // 客户端加密方式需要更换成加密模式 clients.jdbc(dataSource).passwordEncoder(passwordEncoder); // 此处可以修改默认的sql语句 JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource); clients.withClientDetails(clientDetailsService); } @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) { oauthServer .allowFormAuthenticationForClients() .checkTokenAccess("permitAll()") .passwordEncoder(passwordEncoder); } /** * 定义授权Token * @param endpoints * @throws Exception */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { super.configure(endpoints); /* * 用于修改框架默认的访问路径 */ endpoints.authenticationManager(authenticationManager) .tokenStore(tokenStore()) .tokenEnhancer(tokenEnhancer()) .userDetailsService(userDetailsService) .reuseRefreshTokens(false) // 对外开放的登录接口请求方式 .allowedTokenEndpointRequestMethods(HttpMethod.POST) // 更改登录路径为自定义路径 .pathMapping("/oauth/token","/authLoginController/login") .exceptionTranslator(new DefaultWebResponseExceptionTranslator()); } /** * 用户认证信息存放在Redis中,使用RedisStore进行存储 * @return tokenStore */ @Bean public TokenStore tokenStore(){ RedisTokenStore tokenStore = new RedisTokenStore(lettuceConnectionFactory); tokenStore.setPrefix(RedisConstant.REDIS_ACCOUNT_PREFIX); return tokenStore; } @Bean public TokenEnhancer tokenEnhancer(){ final Map<String,Object> additionalInfo = new HashMap<>(3); return (oAuth2AccessToken, oAuth2Authentication) -> { AuthUserDetails authUserDetails = (AuthUserDetails) oAuth2Authentication.getUserAuthentication().getPrincipal(); additionalInfo.put("userId", authUserDetails.getId()); additionalInfo.put("username", authUserDetails.getUsername()); // additionalInfo.put("mobile", authUserDetails.getMobile()); additionalInfo.put("authorities", authUserDetails.getAuthorities()); ((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(additionalInfo); return oAuth2AccessToken; }; } }

security配置:

package com.vevor.mall.auth.config; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.BeanIds; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; /** * @author lixinyu * @data 2020-08-31 */ @Slf4j @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) @Service public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Qualifier("userDetailsServiceImpl") @Autowired private UserDetailsService userDetailsService; /** * http请求设置 * @param http * @throws Exception */ @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() // 释放拦截的请求 .antMatchers("/authLoginController/**") .permitAll() .anyRequest().authenticated() // 关闭打开的csrf保护 .and().csrf().disable() // http基础认证 .httpBasic(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 配置用户密码加密方式,BCrypt实现加密器可以有效防止撞库 auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } @Bean(name = BeanIds.AUTHENTICATION_MANAGER) @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } /** * 密码加密算法 * @return 加密算法,BCrypt实现加密器可以有效防止撞库 */ @Bean public PasswordEncoder passwordEncoder(){ PasswordEncoder encoder = new BCryptPasswordEncoder(); return encoder; } }

实现UserDetailsService:

package com.vevor.mall.auth.config; import com.vevor.mall.auth.entity.AuthUserDetails; import com.vevor.mall.auth.service.IAuthUserService; import com.vevor.mall.auth.vo.UserVO; import org.springframework.beans.BeanUtils; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; /** * @author lixinyu * @date 2020-08-31 * @description 权限框架查询用户详情服务实现类 */ @Service public class UserDetailsServiceImpl implements UserDetailsService { private final IAuthUserService authUserService; public UserDetailsServiceImpl(IAuthUserService authUserService) { this.authUserService = authUserService; } /** * 用户密码登录 * @param username 用户名 * @return UserDetails * @throws UsernameNotFoundException */ @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 根据用户名查询用户的接口 UserVO user = authUserService.queryUserByUsername(username); if (user == null) { throw new UsernameNotFoundException("用户名不存在!"); } return getUserDetails(user); } /** * 构建用户信息 * @param userVO * @return 用户详情 */ private AuthUserDetails getUserDetails(UserVO userVO) { // UserVO是用户实体类,AuthUserDetails是SpringSecurity认证用户详情对象 AuthUserDetails userDetails = new AuthUserDetails(); // 1. 用户详情封装(此处由于是继承关系,可以使用属性复制的方式) BeanUtils.copyProperties(userVO, userDetails); return userDetails; } }

完善查询接口,mapper,mybatis查询即可。

Redis缓存内容可通过工具查看。

 

最新回复(0)