springSecurity入门
依赖
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
|
镇
添加登录及权限
我怎么感觉有点麻烦呢,又是经典白学?
controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @PostMapping("/login") public String login(@RequestBody User user) { UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()); Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
if (Objects.isNull(authenticate)) { throw new RuntimeException("用户名或密码错误"); }
LoginUser principal = (LoginUser) authenticate.getPrincipal(); System.out.println(principal);
return JwtUtil.createToken(principal.getUsername(), principal.getPassword()); }
|
在那些东西之前的jwt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| package cn.sdadgz.security;
import cn.sdadgz.entity.User; import cn.sdadgz.service.IUserService; import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain; 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.Objects;
@Component @RequiredArgsConstructor public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
private final IUserService userService;
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token = request.getHeader("token"); if (Objects.isNull(token)) { filterChain.doFilter(request, response); return; }
User user = userService.getById(4); LoginUser loginUser = new LoginUser(user); loginUser.setPermissions(Collections.singletonList("test"));
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); filterChain.doFilter(request, response); } }
|
controller登录调用的UserDetailsService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package cn.sdadgz.security;
import cn.sdadgz.entity.User; import cn.sdadgz.service.IUserService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; 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;
import java.util.Collections; import java.util.Objects;
@Service @RequiredArgsConstructor public class UserDetailServiceImpl implements UserDetailsService {
private final IUserService userService;
@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(User::getUsername, username); User user = userService.getOne(wrapper); if (Objects.isNull(user)) { throw new RuntimeException("用户名或密码错误"); } return new LoginUser(user, Collections.singletonList("test")); } }
|
UserDetailsServcie使用的UserDetails
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| package cn.sdadgz.security;
import cn.sdadgz.entity.User; import lombok.*; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection; import java.util.List; import java.util.stream.Collectors;
@Getter @Setter @NoArgsConstructor public class LoginUser implements UserDetails {
private User user;
private List<String> permissions;
public LoginUser(User user) { this.user = user; }
public LoginUser(User user, List<String> permissions) { this.user = user; this.permissions = permissions; }
@Override public Collection<? extends GrantedAuthority> getAuthorities() { return permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()); }
@Override public String getPassword() { return user.getPassword(); }
@Override public String getUsername() { return user.getUsername(); }
@Override public boolean isAccountNonExpired() { return true; }
@Override public boolean isAccountNonLocked() { return true; }
@Override public boolean isCredentialsNonExpired() { return true; }
@Override public boolean isEnabled() { return true; } }
|
配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| package cn.sdadgz.security;
import lombok.RequiredArgsConstructor; 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.configuration.EnableGlobalAuthentication; 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.WebSecurityConfiguration; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@RequiredArgsConstructor @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; private final AuthenticationEntryPoint authenticationEntryPoint; private final AccessDeniedHandler accessDeniedHandler;
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
@Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); }
@Override protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers("/user/login", "/user/register").anonymous() .anyRequest().authenticated();
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
http.exceptionHandling() .accessDeniedHandler(accessDeniedHandler) .authenticationEntryPoint(authenticationEntryPoint);
http.cors(); } }
|
使用登录的信息
所有授权信息都在jwt的那里添加,config拦截未授权的访问
退出登录
- 删了redis中的用户信息
- jwt那里发现取不到redis值
- 抛出用户未登录
- 结束
权限注解
- 配置文件加上
@EnableGlobalMethodSecurity(prePostEnabled = true)
注解,去掉冗余的@Configuration
注解
- 需要特定权限的
controller
设置 @PreAuthorize("hasAuthority('test')")
或
- 同上第一步
- 。。。设置
@PreAuthorize("@[my.compoment].hasAuthority('test')")
自定义权限验证类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package cn.sdadgz.security;
import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component;
import java.util.Collection; import java.util.List;
@Component public class Ex { public static boolean hasAuthority(String auth){ Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); LoginUser loginUser = (LoginUser) authentication.getPrincipal(); Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); List<String> permissions = loginUser.getPermissions();
return true; } }
|
其他
- 登录成功处理器
- 登录失败处理器
- 登出成功处理器
- 。。。
例一:
需要在配置中加上对应配置,似乎像是废话
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package cn.sdadgz.security;
import cn.hutool.json.JSON; import cn.hutool.json.JSONUtil; import cn.sdadgz.exception.MyException; import cn.sdadgz.utils.WebUtil; import org.springframework.http.codec.cbor.Jackson2CborEncoder; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.stereotype.Component;
import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;
@Component public class AccessDeniedHandlerImpl implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws MyException { String json = JSONUtil.toJsonStr("权限不足"); WebUtil.renderString(response, json); } }
|
例二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package cn.sdadgz.security;
import cn.hutool.json.JSONUtil; import cn.sdadgz.exception.MyException; import cn.sdadgz.utils.WebUtil; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component;
import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;
@Component public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws MyException { String json = JSONUtil.toJsonStr("认证失败"); WebUtil.renderString(response, json); } }
|