公司新来了一个同事,把权限系统设计的炉火纯青!
后台回复:1024,获取海量学习资源
SQL刷题专栏
SQL145题系列
大家注意:
因为微信改了推送机制,会有小伙伴刷不到当天的文章,
一些比较实用的知识和信息,错过了就是错过了。
所以建议大家加个星标
,就能第一时间收到推送了。

-
角色互斥
-
基数约束
-
先决条件
-
运行时互斥
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>
package com.example.demo.web;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/test")public class Test {@RequestMapping("/test")public String test(){return "test";}}
用户名:user密码 984cccf2-ba82-468e-a404-7d32123d0f9c
spring:security:user:name: mingpassword: 123456roles: admin
package com.example.demo.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.crypto.password.NoOpPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;@Configurationpublic class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {@BeanPasswordEncoder passwordEncoder(){return NoOpPasswordEncoder.getInstance();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("admin").password("123").roles("admin");}}
package com.ming.demo.interceptor;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.HttpMethod;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.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;public class SecurityConfig extends WebSecurityConfigurerAdapter {//基于内存的用户存储public void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("itguang").password("123456").roles("USER").and().withUser("admin").password("{noop}" + "123456").roles("ADMIN");}//请求拦截protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().permitAll().and().formLogin().permitAll().and().logout().permitAll();}}
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId><version>2.3.1.RELEASE</version></dependency>
package com.example.demo;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;public class JwtUser implements UserDetails {private String username;private String password;private Integer state;private Collection<? extends GrantedAuthority> authorities;public JwtUser(){}public JwtUser(String username, String password, Integer state, Collection<? extends GrantedAuthority> authorities){this.username = username;this.password = password;this.state = state;this.authorities = authorities;}public Collection<? extends GrantedAuthority> getAuthorities() {return authorities;}public String getPassword() {return this.password;}public String getUsername() {return this.username;}public boolean isAccountNonExpired() {return true;}public boolean isAccountNonLocked() {return true;}public boolean isCredentialsNonExpired() {return true;}public boolean isEnabled() {return true;}}
package com.example.demo;import io.jsonwebtoken.Claims;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import org.springframework.security.core.userdetails.UserDetails;import java.io.Serializable;import java.util.Date;import java.util.HashMap;import java.util.Map;public class JwtTokenUtil implements Serializable {private String secret;private Long expiration;private String header;private String generateToken(Map<String, Object> claims) {Date expirationDate = new Date(System.currentTimeMillis() + expiration);return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, secret).compact();}private Claims getClaimsFromToken(String token) {Claims claims;try {claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();} catch (Exception e) {claims = null;}return claims;}public String generateToken(UserDetails userDetails) {Map<String, Object> claims = new HashMap<>(2);claims.put("sub", userDetails.getUsername());claims.put("created", new Date());return generateToken(claims);}public String getUsernameFromToken(String token) {String username;try {Claims claims = getClaimsFromToken(token);username = claims.getSubject();} catch (Exception e) {username = null;}return username;}public Boolean isTokenExpired(String token) {try {Claims claims = getClaimsFromToken(token);Date expiration = claims.getExpiration();return expiration.before(new Date());} catch (Exception e) {return false;}}public String refreshToken(String token) {String refreshedToken;try {Claims claims = getClaimsFromToken(token);claims.put("created", new Date());refreshedToken = generateToken(claims);} catch (Exception e) {refreshedToken = null;}return refreshedToken;}public Boolean validateToken(String token, UserDetails userDetails) {JwtUser user = (JwtUser) userDetails;String username = getUsernameFromToken(token);return (username.equals(user.getUsername()) && !isTokenExpired(token));}}
package com.example.demo;import org.apache.commons.lang.StringUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;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;public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {private UserDetailsService userDetailsService;private JwtTokenUtil jwtTokenUtil;protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {String authHeader = httpServletRequest.getHeader(jwtTokenUtil.getHeader());if (authHeader != null && StringUtils.isNotEmpty(authHeader)) {String username = jwtTokenUtil.getUsernameFromToken(authHeader);if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);if (jwtTokenUtil.validateToken(authHeader, userDetails)) {UsernamePasswordAuthenticationToken authentication =new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));SecurityContextHolder.getContext().setAuthentication(authentication);}}}filterChain.doFilter(httpServletRequest, httpServletResponse);}}
package com.example.demo;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.userdetails.User;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 javax.management.relation.Role;import java.util.List;public class JwtUserDetailsServiceImpl implements UserDetailsService {private UserMapper userMapper;public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {User user = userMapper.selectByUserName(s);if (user == null) {throw new UsernameNotFoundException(String.format("'%s'.这个用户不存在", s));}List<SimpleGrantedAuthority> collect = user.getRoles().stream().map(Role::getRolename).map(SimpleGrantedAuthority::new).collect(Collectors.toList());return new JwtUser(user.getUsername(), user.getPassword(), user.getState(), collect);}}
public class UserServiceImpl implements UserService {private UserMapper userMapper;private AuthenticationManager authenticationManager;private UserDetailsService userDetailsService;private JwtTokenUtil jwtTokenUtil;public User findByUsername(String username) {User user = userMapper.selectByUserName(username);return user;}public RetResult login(String username, String password) throws AuthenticationException {UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);final Authentication authentication = authenticationManager.authenticate(upToken);SecurityContextHolder.getContext().setAuthentication(authentication);UserDetails userDetails = userDetailsService.loadUserByUsername(username);return new RetResult(RetCode.SUCCESS.getCode(),jwtTokenUtil.generateToken(userDetails));}}
(prePostEnabled = true)public class WebSecurity extends WebSecurityConfigurerAdapter {private UserDetailsService userDetailsService;private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {authenticationManagerBuilder.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder());}(name = BeanIds.AUTHENTICATION_MANAGER)public AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}public PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}protected void configure(HttpSecurity http) throws Exception {http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll().antMatchers("/auth/**").permitAll().anyRequest().authenticated().and().headers().cacheControl();http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.authorizeRequests();registry.requestMatchers(CorsUtils::isPreFlightRequest).permitAll();}public CorsFilter corsFilter() {final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();final CorsConfiguration cors = new CorsConfiguration();cors.setAllowCredentials(true);cors.addAllowedOrigin("*");cors.addAllowedHeader("*");cors.addAllowedMethod("*");urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", cors);return new CorsFilter(urlBasedCorsConfigurationSource);}}
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {//attempt Authentication when Content-Type is jsonif(request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)||request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)){//use jackson to deserialize jsonObjectMapper mapper = new ObjectMapper();UsernamePasswordAuthenticationToken authRequest = null;try (InputStream is = request.getInputStream()){AuthenticationBean authenticationBean = mapper.readValue(is,AuthenticationBean.class);authRequest = new UsernamePasswordAuthenticationToken(authenticationBean.getUsername(), authenticationBean.getPassword());}catch (IOException e) {e.printStackTrace();authRequest = new UsernamePasswordAuthenticationToken("", "");}finally {setDetails(request, authRequest);return this.getAuthenticationManager().authenticate(authRequest);}}//transmit it to UsernamePasswordAuthenticationFilterelse {return super.attemptAuthentication(request, response);}}}
protected void configure(HttpSecurity http) throws Exception {http.cors().and().antMatcher("/**").authorizeRequests().antMatchers("/", "/login**").permitAll().anyRequest().authenticated()//这里必须要写formLogin(),不然原有的UsernamePasswordAuthenticationFilter不会出现,也就无法配置我们重新的UsernamePasswordAuthenticationFilter.and().formLogin().loginPage("/").and().csrf().disable();//用重写的Filter替换掉原有的UsernamePasswordAuthenticationFilterhttp.addFilterAt(customAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);}//注册自定义的UsernamePasswordAuthenticationFilterCustomAuthenticationFilter customAuthenticationFilter() throws Exception {CustomAuthenticationFilter filter = new CustomAuthenticationFilter();filter.setAuthenticationSuccessHandler(new SuccessHandler());filter.setAuthenticationFailureHandler(new FailureHandler());filter.setFilterProcessesUrl("/login/self");//这句很关键,重用WebSecurityConfigurerAdapter配置的AuthenticationManager,不然要自己组装AuthenticationManagerfilter.setAuthenticationManager(authenticationManagerBean());return filter;}
/*** 密码加密*/@Beanpublic BCryptPasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
public class UserServiceImpl implements UserService {private UserRepository userRepository;private BCryptPasswordEncoder bCryptPasswordEncoder; //注入bcryct加密public User add(User user) {user.setPassword(bCryptPasswordEncoder.encode(user.getPassword())); //对密码进行加密User user2 = userRepository.save(user);return user2;}public ResultInfo login(User user) {ResultInfo resultInfo=new ResultInfo();User user2 = userRepository.findByName(user.getName());if (user2==null) {resultInfo.setCode("-1");resultInfo.setMessage("用户名不存在");return resultInfo;}//判断密码是否正确if (!bCryptPasswordEncoder.matches(user.getPassword(),user2.getPassword())) {resultInfo.setCode("-1");resultInfo.setMessage("密码不正确");return resultInfo;}resultInfo.setMessage("登录成功");return resultInfo;}}
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {private UserService userService; // service 层注入PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}protected void configure(AuthenticationManagerBuilder auth) throws Exception {// 参数传入Service,进行验证auth.userDetailsService(userService);}protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/admin/**").hasRole("admin").anyRequest().authenticated().and().formLogin().loginProcessingUrl("/login").permitAll().and().csrf().disable();}}
最后给大家分享我写的SQL两件套:《SQL基础知识第二版》和《SQL高级知识第二版》的PDF电子版。里面有各个语法的解释、大量的实例讲解和批注等等,非常通俗易懂,方便大家跟着一起来实操。
有需要的读者可以下载学习,在下面的公众号「数据前线」(非本号)后台回复关键字:SQL,就行
数据前线
后台回复关键字:1024,获取一份精心整理的技术干货
后台回复关键字:进群,带你进入高手如云的交流群。
推荐阅读
MySQL为啥不能用uuid做主键?!
97条 Linux 常用命令总结
“秒杀”问题的数据库和SQL设计
MySQL:互联网公司常用分库分表方案汇总
掌握 SQL 这些核心知识点,出去吹牛逼再也不担心了 ![]()
评论

