|
@@ -0,0 +1,173 @@
|
|
|
+package com.fdkankan.auth.config;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.auth0.jwt.JWT;
|
|
|
+import com.auth0.jwt.algorithms.Algorithm;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.fdkankan.auth.service.impl.UserDetailsServiceImpl;
|
|
|
+import com.fdkankan.common.constant.ErrorCode;
|
|
|
+import com.fdkankan.common.filter.JwtTokenFilter;
|
|
|
+import com.fdkankan.common.response.ResultData;
|
|
|
+import com.fdkankan.redis.util.RedisUtil;
|
|
|
+import java.io.PrintWriter;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collection;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import javax.annotation.Resource;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.context.annotation.Bean;
|
|
|
+import org.springframework.context.annotation.Configuration;
|
|
|
+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.configuration.EnableWebSecurity;
|
|
|
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
|
+import org.springframework.security.core.GrantedAuthority;
|
|
|
+import org.springframework.security.core.userdetails.User;
|
|
|
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
|
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
|
|
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
|
|
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
|
|
+
|
|
|
+/**
|
|
|
+ * <p>
|
|
|
+ * TODO
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @author dengsixing
|
|
|
+ * @since 2022/4/2
|
|
|
+ **/
|
|
|
+@Configuration
|
|
|
+@EnableWebSecurity
|
|
|
+@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级别安全
|
|
|
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
|
+ @Resource
|
|
|
+ private UserDetailsServiceImpl userDetailsService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisUtil redisUtil;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private JwtTokenFilter jwtTokenFilter;
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ public BCryptPasswordEncoder bCryptPasswordEncoder() {
|
|
|
+ return new BCryptPasswordEncoder();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 一些简单的配置
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ protected void configure(HttpSecurity http) throws Exception {
|
|
|
+ http.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
|
|
+
|
|
|
+ // 禁用session
|
|
|
+ http.sessionManagement().disable();
|
|
|
+ http.csrf().disable();
|
|
|
+ http.formLogin()
|
|
|
+ // 自定义登录成功后路径
|
|
|
+ .successHandler(authenticationSuccessHandler())
|
|
|
+ // 自定义登录路径
|
|
|
+ .failureHandler(authenticationFailureHandler());
|
|
|
+ // 可以匿名访问
|
|
|
+ http.authorizeRequests()
|
|
|
+ .antMatchers("/auth/login").anonymous()
|
|
|
+ .anyRequest().authenticated()
|
|
|
+ ;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
|
|
+ // 用户数据从数据库获取
|
|
|
+ auth.userDetailsService(userDetailsService);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 用密码模式授权认证管理器
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ @Bean
|
|
|
+ @Override
|
|
|
+ public AuthenticationManager authenticationManager() throws Exception{
|
|
|
+ return super.authenticationManager();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 登录成功处理器
|
|
|
+ */
|
|
|
+ @Bean
|
|
|
+ public AuthenticationSuccessHandler authenticationSuccessHandler() {
|
|
|
+ return ((httpServletRequest, httpServletResponse, authentication) -> {
|
|
|
+ httpServletResponse.setContentType("application/json;charset=utf-8");
|
|
|
+ User user = (User)authentication.getPrincipal();
|
|
|
+ // 用户名
|
|
|
+ String username = user.getUsername();
|
|
|
+ // 密码
|
|
|
+ String password = user.getPassword();
|
|
|
+ // 权限
|
|
|
+ Collection<GrantedAuthority> grantedAuthorities = user.getAuthorities();
|
|
|
+ List<String> roleList = new ArrayList<>();
|
|
|
+ grantedAuthorities.forEach(grantedAuthority -> {
|
|
|
+ roleList.add(grantedAuthority.getAuthority());
|
|
|
+ });
|
|
|
+ String[] roles = new String[roleList.size()];
|
|
|
+ // 用jwt生成token
|
|
|
+ HashMap<String, Object> headMap = new HashMap<>(16);
|
|
|
+ // 使用的算法
|
|
|
+ headMap.put("alg", "HS256");
|
|
|
+ headMap.put("typ", "JWT");
|
|
|
+ Date nowDate = new Date();
|
|
|
+ // 过期时间可以自定义
|
|
|
+ Date expDate = new Date(nowDate.getTime() + 2 * 60 * 60 * 1000);
|
|
|
+ String jwt = JWT.create().withHeader(headMap)
|
|
|
+ .withIssuedAt(nowDate)
|
|
|
+ .withExpiresAt(expDate)
|
|
|
+ // 主题,自定义
|
|
|
+ .withSubject("demo")
|
|
|
+ .withClaim("username", username)
|
|
|
+ .withClaim("password", password)
|
|
|
+ .withArrayClaim("role", roleList.toArray(roles))
|
|
|
+ // 签名,自定义,同一个项目中签名是唯一
|
|
|
+ .sign(Algorithm.HMAC256("test"));
|
|
|
+ // 保存token到redis
|
|
|
+ redisUtil.set("token:" + jwt, JSON.toJSONString(user), 7200);
|
|
|
+ // 返回token
|
|
|
+ HashMap<String, Object> hashMap = new HashMap<>(16);
|
|
|
+ hashMap.put("username", username);
|
|
|
+ hashMap.put("create_time", nowDate);
|
|
|
+ hashMap.put("expires_time", expDate);
|
|
|
+ hashMap.put("access_token", jwt);
|
|
|
+ hashMap.put("type", "bearer");
|
|
|
+ ObjectMapper objectMapper = new ObjectMapper();
|
|
|
+ String s = objectMapper.writeValueAsString(hashMap);
|
|
|
+ PrintWriter printWriter = httpServletResponse.getWriter();
|
|
|
+ printWriter.write(s);
|
|
|
+ printWriter.flush();
|
|
|
+ printWriter.close();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 登录失败处理器
|
|
|
+ */
|
|
|
+ @Bean
|
|
|
+ public AuthenticationFailureHandler authenticationFailureHandler() {
|
|
|
+ return ((httpServletRequest, httpServletResponse, e) -> {
|
|
|
+ httpServletResponse.setCharacterEncoding("UTF-8");
|
|
|
+ ResultData error = ResultData.error(ErrorCode.PASSWORD_ERROR);
|
|
|
+ ObjectMapper objectMapper = new ObjectMapper();
|
|
|
+ String s = objectMapper.writeValueAsString(error);
|
|
|
+ PrintWriter printWriter = httpServletResponse.getWriter();
|
|
|
+ printWriter.write(s);
|
|
|
+ printWriter.flush();
|
|
|
+ printWriter.close();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+}
|