Initial commit
This commit is contained in:
		@@ -38,5 +38,10 @@
 | 
			
		||||
            <artifactId>spring-boot-starter-web</artifactId>
 | 
			
		||||
            <scope>provided</scope>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <!--        redis-->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
            <artifactId>spring-boot-starter-data-redis</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
    </dependencies>
 | 
			
		||||
</project>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,22 @@
 | 
			
		||||
package com.atguigu.security.config;
 | 
			
		||||
 | 
			
		||||
import com.atguigu.security.custom.CustomMd5PasswordEncoder;
 | 
			
		||||
import com.atguigu.security.filter.TokenAuthenticationFilter;
 | 
			
		||||
import com.atguigu.security.filter.TokenLoginFilter;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.data.redis.core.RedisTemplate;
 | 
			
		||||
import org.springframework.security.authentication.AuthenticationManager;
 | 
			
		||||
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.config.http.SessionCreationPolicy;
 | 
			
		||||
import org.springframework.security.core.userdetails.UserDetailsService;
 | 
			
		||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ClassName: WebSecurityConfig
 | 
			
		||||
@@ -14,6 +28,66 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
 | 
			
		||||
@Configuration
 | 
			
		||||
//@EnableWebSecurity是开启SpringSecurity的默认行为
 | 
			
		||||
@EnableWebSecurity
 | 
			
		||||
//开启基于方法的安全认证机制,在web层的controller启用注解机制的安全确认
 | 
			
		||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
 | 
			
		||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 装载的是 org.springframework.security.core.userdetails.UserDetailsService;
 | 
			
		||||
     */
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private UserDetailsService userDetailsService;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private CustomMd5PasswordEncoder customMd5PasswordEncoder;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RedisTemplate redisTemplate;
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    @Override
 | 
			
		||||
    protected AuthenticationManager authenticationManager() throws Exception {
 | 
			
		||||
        return super.authenticationManager();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void configure(HttpSecurity http) throws Exception {
 | 
			
		||||
        // 这是配置的关键,决定哪些接口开启防护,哪些接口绕过防护
 | 
			
		||||
        http
 | 
			
		||||
                //关闭csrf跨站请求伪造
 | 
			
		||||
                .csrf().disable()
 | 
			
		||||
                // 开启跨域以便前端调用接口
 | 
			
		||||
                .cors().and()
 | 
			
		||||
                .authorizeRequests()
 | 
			
		||||
                // 指定某些接口不需要通过验证即可访问。登陆接口肯定是不需要认证的
 | 
			
		||||
                .antMatchers("/admin/system/index/login").permitAll()
 | 
			
		||||
                // 这里意思是其它所有接口需要认证才能访问
 | 
			
		||||
                .anyRequest().authenticated()
 | 
			
		||||
                .and()
 | 
			
		||||
                //TokenAuthenticationFilter放到UsernamePasswordAuthenticationFilter的前面,这样做就是为了除了登录的时候去查询数据库外,其他时候都用token进行认证。
 | 
			
		||||
                .addFilterBefore(new TokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter.class)
 | 
			
		||||
                .addFilter(new TokenLoginFilter(authenticationManager(), redisTemplate));
 | 
			
		||||
 | 
			
		||||
        //禁用session
 | 
			
		||||
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
 | 
			
		||||
        // 指定UserDetailService和加密器
 | 
			
		||||
        auth.userDetailsService(userDetailsService)
 | 
			
		||||
                .passwordEncoder(customMd5PasswordEncoder);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 配置哪些请求不拦截
 | 
			
		||||
     * 排除swagger相关请求
 | 
			
		||||
     *
 | 
			
		||||
     * @param web
 | 
			
		||||
     * @throws Exception
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void configure(WebSecurity web) throws Exception {
 | 
			
		||||
        web.ignoring().antMatchers("/favicon.ico", "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**", "/doc.html");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
 | 
			
		||||
 * @author yovinchen
 | 
			
		||||
 * @Create 2023/6/10 23:28
 | 
			
		||||
 */
 | 
			
		||||
public interface UserDetailsService {
 | 
			
		||||
public interface UserDetailsService extends org.springframework.security.core.userdetails.UserDetailsService {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据用户名获取用户对象(获取不到直接抛异常)
 | 
			
		||||
@@ -19,5 +19,6 @@ public interface UserDetailsService {
 | 
			
		||||
     * @return
 | 
			
		||||
     * @throws UsernameNotFoundException
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,13 @@
 | 
			
		||||
package com.atguigu.security.filter;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.fastjson.JSON;
 | 
			
		||||
import com.atguigu.common.jwt.JwtHelper;
 | 
			
		||||
import com.atguigu.common.result.Result;
 | 
			
		||||
import com.atguigu.common.result.ResultCodeEnum;
 | 
			
		||||
import com.atguigu.common.utils.ResponseUtil;
 | 
			
		||||
import org.springframework.data.redis.core.RedisTemplate;
 | 
			
		||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 | 
			
		||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
 | 
			
		||||
import org.springframework.security.core.context.SecurityContextHolder;
 | 
			
		||||
import org.springframework.util.StringUtils;
 | 
			
		||||
import org.springframework.web.filter.OncePerRequestFilter;
 | 
			
		||||
@@ -14,7 +17,9 @@ import javax.servlet.ServletException;
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
import javax.servlet.http.HttpServletResponse;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ClassName: TokenAuthenticationFilter
 | 
			
		||||
@@ -26,8 +31,10 @@ import java.util.Collections;
 | 
			
		||||
 */
 | 
			
		||||
public class TokenAuthenticationFilter extends OncePerRequestFilter {
 | 
			
		||||
 | 
			
		||||
    public TokenAuthenticationFilter() {
 | 
			
		||||
    private RedisTemplate redisTemplate;
 | 
			
		||||
 | 
			
		||||
    public TokenAuthenticationFilter(RedisTemplate redisTemplate) {
 | 
			
		||||
        this.redisTemplate = redisTemplate;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -55,8 +62,22 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
 | 
			
		||||
        if (!StringUtils.isEmpty(token)) {
 | 
			
		||||
            String useruame = JwtHelper.getUsername(token);
 | 
			
		||||
            logger.info("useruame:" + useruame);
 | 
			
		||||
            //认证成功
 | 
			
		||||
            if (!StringUtils.isEmpty(useruame)) {
 | 
			
		||||
                return new UsernamePasswordAuthenticationToken(useruame, null, Collections.emptyList());
 | 
			
		||||
                //通过username从reids中获取权限数据
 | 
			
		||||
                String authString = (String) redisTemplate.opsForValue().get(useruame);
 | 
			
		||||
                //将redis中获取的字符串权限数据转换为 ArrayList<SimpleGrantedAuthority>
 | 
			
		||||
                if (!StringUtils.isEmpty(authString)) {
 | 
			
		||||
                    List<Map> mapList = JSON.parseArray(authString, Map.class);
 | 
			
		||||
                    System.out.println(mapList);
 | 
			
		||||
                    List<SimpleGrantedAuthority> authList = new ArrayList<>();
 | 
			
		||||
                    for (Map map : mapList) {
 | 
			
		||||
                        authList.add(new SimpleGrantedAuthority((String) map.get("authority")));
 | 
			
		||||
                    }
 | 
			
		||||
                    return new UsernamePasswordAuthenticationToken(useruame, null, authList);
 | 
			
		||||
                } else {
 | 
			
		||||
                    return new UsernamePasswordAuthenticationToken(useruame, null, new ArrayList<>());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package com.atguigu.security.filter;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.fastjson.JSON;
 | 
			
		||||
import com.atguigu.common.jwt.JwtHelper;
 | 
			
		||||
import com.atguigu.common.result.Result;
 | 
			
		||||
import com.atguigu.common.result.ResultCodeEnum;
 | 
			
		||||
@@ -7,6 +8,7 @@ import com.atguigu.common.utils.ResponseUtil;
 | 
			
		||||
import com.atguigu.security.custom.CustomUser;
 | 
			
		||||
import com.atguigu.vo.system.LoginVo;
 | 
			
		||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
import org.springframework.data.redis.core.RedisTemplate;
 | 
			
		||||
import org.springframework.security.authentication.AuthenticationManager;
 | 
			
		||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 | 
			
		||||
import org.springframework.security.core.Authentication;
 | 
			
		||||
@@ -31,13 +33,15 @@ import java.util.Map;
 | 
			
		||||
 * @Create 2023/6/10 23:37
 | 
			
		||||
 */
 | 
			
		||||
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
 | 
			
		||||
    private RedisTemplate redisTemplate;
 | 
			
		||||
 | 
			
		||||
    // 构造方法
 | 
			
		||||
    public TokenLoginFilter(AuthenticationManager authenticationManager) {
 | 
			
		||||
    public TokenLoginFilter(AuthenticationManager authenticationManager, RedisTemplate redisTemplate) {
 | 
			
		||||
        this.setAuthenticationManager(authenticationManager);
 | 
			
		||||
        this.setPostOnly(false);
 | 
			
		||||
        //指定登录接口及提交方式,可以指定任意路径
 | 
			
		||||
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/system/index/login", "POST"));
 | 
			
		||||
        this.redisTemplate = redisTemplate;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 登录认证过程
 | 
			
		||||
@@ -69,6 +73,8 @@ public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
 | 
			
		||||
        // 生成token
 | 
			
		||||
        String token = JwtHelper.createToken(customUser.getSysUser().getId(), customUser.getSysUser().getUsername());
 | 
			
		||||
 | 
			
		||||
        //获取当前用户权限数据,放到Reids中,key: username value:权限数据
 | 
			
		||||
        redisTemplate.opsForValue().set(customUser.getUsername(), JSON.toJSONString(customUser.getAuthorities()));
 | 
			
		||||
        // 返回
 | 
			
		||||
        Map<String, Object> map = new HashMap<>();
 | 
			
		||||
        map.put("token", token);
 | 
			
		||||
@@ -81,7 +87,7 @@ public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
 | 
			
		||||
                                              AuthenticationException e) throws IOException, ServletException {
 | 
			
		||||
 | 
			
		||||
        if (e.getCause() instanceof RuntimeException) {
 | 
			
		||||
            ResponseUtil.out(response, Result.build(null, ResultCodeEnum.DATA_ERROR));
 | 
			
		||||
            ResponseUtil.out(response, Result.build(null, ResultCodeEnum.LOGIN_ERROR));
 | 
			
		||||
        } else {
 | 
			
		||||
            ResponseUtil.out(response, Result.build(null, ResultCodeEnum.LOGIN_AUTH));
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user