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

首先引入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缓存内容可通过工具查看。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值