![]()
package shang.config;
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.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.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.OncePerRequestFilter;
import shang.handle.*;
import shang.service.UserDetailsServiceImpl;
import javax.sql.DataSource;
/**
* @Auther: 三尾鱼
* @Date: 2020/11/23 08:51
* @Description:
*/
//@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
//开启注解方式,的鉴权判断,
// 其中securedEnabled = true 是基于角色的注解;
//prePostEnabled = true 是基于access表达式的注解,即可以角色,又可以权限因子
@Configuration
public class SecurityConfig02 extends WebSecurityConfigurerAdapter
{
/* @Autowired
DataSource dataSource;
*/
@Autowired
UserDetailsServiceImpl userDetailsServiceImpl;
@Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService (userDetailsServiceImpl).passwordEncoder (passwordEncoder ());
}
//要实现自定义登录页面,必须继承 WebSecurityConfigurerAdapter 并且重写 configure(HttpSecurity http)
/**
* anyRequest | 匹配所有请求路径
* access | SpringEl表达式结果为true时可以访问
* anonymous | 匿名可以访问
* denyAll | 用户不能访问
* fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录)
* hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问
* hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问
* hasAuthority | 如果有参数,参数表示权限,则其权限可以访问
* hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
* hasRole | 如果有参数,参数表示角色,则其角色可以访问
* permitAll | 用户可以任意访问
* rememberMe | 允许通过remember-me登录的用户访问
* authenticated | 用户登录后可访问
*/
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.cors ().and ().csrf ().disable ()
//不要session
.sessionManagement ().sessionCreationPolicy (SessionCreationPolicy.STATELESS);
//未登陆时返回 JSON 格式的数据给前端,否则是html
http.httpBasic ().authenticationEntryPoint (restAuthenticationEntryPoint);
http.formLogin ()//表单提交
.usernameParameter ("username123")//自定义如蝉,缺省是username 和 password
.passwordParameter ("password123")//如果登录页面中没有,登录都会失败
.loginPage ("/login")//自定义登录页面 都不要带后缀
//还要指定自定义登录的URL,必须和表单提交的接口一样,这样才能触发自定义登录逻辑
.loginProcessingUrl ("/login")//url /login 是login.html 页面的action
//.successForwardUrl ("/toSuccess")//登录成功后,跳转的URL,需要post请求
//.successForwardUrl ("http://www.baidu.com")//这种方式行不通
//.successHandler (new 自定义成功跳转逻辑类 ("http://www.baidu.com"))
.successHandler (new 登录成功处理器 ("/toSuccess"))//登录成功处理器
//真正的前后端分离开发,这里无论成功与否,都返回JSON字符串和令牌,让前端自己决定如何处理
//.failureForwardUrl ("/toError");//登录失败,跳转的URL ,需要post请求
.failureHandler (new 登录失败处理器 (""));//登录失败处理器
// 【异常处理】之 鉴权失败处理器 要另起一行单独配置
http.exceptionHandling ().accessDeniedHandler (new 鉴权失败处理器 ());
//加入自定义授权过滤器
http.addFilter (new JWTAuthorizationFilter (authenticationManager ()));
//实践证明:如果不把凭证放进spring security的上下文,将访问不到任何需要认证才放行的URL,
// 自定义此拦截器的就是为了在每次请求都把Head中的token解密后的用户凭证放进上下文
//至于权限验证,交给框架完成,当然如果你想自定义就覆盖框架的相应过滤器
//这2个过滤器是等价的
//http.addFilterBefore (new 每次请求拦截一次过滤器 (), UsernamePasswordAuthenticationFilter.class);
//开启记住我 功能
/*http.rememberMe ()
//设置数据源
.tokenRepository (persistentTokenRepository ())
//设置超时时间,缺省是2周,这里设置60秒
.tokenValiditySeconds (60)
//自定义登录逻辑,必选项
.userDetailsService (userDetailsServiceImpl);*/
//退出配置
http.logout ()
//退出成功后,跳转的页面
.logoutSuccessUrl ("/login");
//授权
http.authorizeRequests ()
//antMatchers方法中的通配符?=任何一个字符 *=任意多个字符 **=任意多个目录
//.antMatchers ("/js/**", "/css/**", "/img/**").permitAll () //放行所有静态资源
//.antMatchers ("/**/*.png").permitAll () //放行所有后缀是png的图片资源
.regexMatchers (".+\\.png").permitAll () //使用正则表达式匹配
.regexMatchers (HttpMethod.POST, "/demo").permitAll () //必须是post请求
.antMatchers ("/login").permitAll ()//必须放行登录URL,否则会报 重定向次数过多
.antMatchers ("/toError").permitAll ()//必须放行登录失败的URL,否则会报 重定向次数过多
//.antMatchers ("/admin").hasAuthority ("admin")//严格区分大小写,基于权限因子的访问控制
//.antMatchers ("/admin").hasAnyAuthority ("admin","Admin")
//hasAnyAuthority 严格区分大小写,基于权限因子的访问控制,有任意一个权限因子都可以访问
//基于角色的访问控制,严格区分大小写,授权失败,如何返回JSON字符串
//.antMatchers ("/admin").hasAnyRole ("Admin","useR")//注意点:角色名,不用添加前缀【ROLE_】
//.antMatchers ("/admin").access ("hasAnyRole('admin1','user1')")
//基于IP地址的访问控制
//.antMatchers ("/admin").hasIpAddress ("227.0.0.1")
//所有请求都必须认证,就是必须登录,才能访问
.anyRequest ().authenticated ();
//自定义的access方法
//.anyRequest ().access ("@myAccessControImpl.hasPermission(request,authentication)");
}
@Bean
PasswordEncoder passwordEncoder()
{
return new BCryptPasswordEncoder ();
}
//记住我的时候,添加的这个
/*@Bean
public PersistentTokenRepository persistentTokenRepository()
{
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl ();
//设置数据源
tokenRepository.setDataSource (dataSource);
//设置 自动建表,第一次使用,第二次注释,否则每次建表会覆盖掉原来记录
tokenRepository.setCreateTableOnStartup (false);
return tokenRepository;
}*/
//容许跨站请求
@Bean
CorsConfigurationSource corsConfigurationSource()
{
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource ();
source.registerCorsConfiguration ("/**", new CorsConfiguration ().applyPermitDefaultValues ());
return source;
}
}
package shang.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import shang.entity.JsonMsg;
/**
* @Auther: 三尾鱼
* @Date: 2021/2/19 12:33
* @Description:
*/
@Controller
public class HomeController
{
@RequestMapping("/login")
public ModelAndView login(ModelAndView mv)
{
mv.setViewName ("/login");//设置视图名
return mv;
}
//@Secured ("ROLE_user3")
//@PreAuthorize ("hasRole('user')")
//@PreAuthorize ("hasRole('ROLE_user')") //可以使用ROLE_ 前缀
@PreAuthorize ("hasAnyAuthority('admin','user')")//基于权限因子的 鉴权
@RequestMapping("/toSuccess")
public ModelAndView toSuccess(ModelAndView mv)
{
mv.setViewName ("/main");//设置视图名
return mv;
}
// @RequestMapping("/toError")
// public ModelAndView toError(ModelAndView mv)
// {
// mv.setViewName ("/error");
// 设置视图名,如果templates下面有特别error.html 页面,发生权限不够,将自动关联到error.html
//如果没有error.html 将显示403
// return mv;
// }
@RequestMapping("/demo")
@ResponseBody
public JsonMsg demo()
{
JsonMsg jsonMsg =new JsonMsg ();
jsonMsg.setMsg ("张三");
jsonMsg.setStatusCode (200);
return jsonMsg;
}
@PreAuthorize ("hasAnyAuthority('admin','user33')")//基于权限因子的 鉴权
@RequestMapping("/admin")
public String admin(){
return "admin";
}
@RequestMapping("/showspringsecurity5")
public String show_springsecurity5(){
return "show-springsecurity5";
}
}
package shang.handle;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
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.ArrayList;
/**
* @Auther: Administrator
* @Date: 2021/2/21 14:19
* @Description:
*/
public class JWTAuthorizationFilter extends BasicAuthenticationFilter
{
public JWTAuthorizationFilter(AuthenticationManager authenticationManager)
{
super (authenticationManager);
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws IOException, ServletException
{
//String tokenHeader = "123";//request.getHeader(JwtTokenUtils.TOKEN_HEADER);
// 如果请求头中没有Authorization信息则直接放行了
//if (tokenHeader == null || !tokenHeader.startsWith(JwtTokenUtils.TOKEN_PREFIX)) {
/* if (tokenHeader == null || tokenHeader.equals ("123"))
{
//抛出鉴权失败异常
//throw new AccessDeniedException("403,无token");
//实践怎么,拿不到token,就返回到登陆页面
chain.doFilter (request, response);
return;
}*/
//chain.doFilter (request, response);
// 如果请求头中有token,则进行解析,并且设置认证信息
//SecurityContextHolder.getContext ().setAuthentication (getAuthentication (tokenHeader));
//super.doFilterInternal (request, response, chain);
//测试做个简易版
String authHeader =null;
try
{
authHeader =request.getHeader("token");//Authorization
//token里面包含有1、用户名 2、权限因子和角色
if (authHeader == null || authHeader.trim ().length () == 0)
{
}
else {
String username = "admin";
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken (username, null, AuthorityUtils.commaSeparatedStringToAuthorityList
("admin,normal,ROLE_admin,ROLE_user,/toSuccess,/insert,/delete"));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
//new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities ());
}catch (AuthenticationException e) {
System.out.println ("AuthenticationException="+e.getMessage ());
}
finally
{
//实践证明:如果不把凭证放进spring security的上下文,将访问不到任何需要认证才放行的URL,
// 自定义此拦截器的就是为了在每次请求都把Head中的token解密后的用户凭证放进上下文
//至于权限验证,交给框架完成,当然如果你想自定义就覆盖框架的相应过滤器
chain.doFilter(request, response);//如果上下文有认证信息,就跳过认证页面进入鉴权,如果没有认证信息,直接重定向到认证页面
}
}
// 这里从token中获取用户信息并新建一个token
private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader)
{
String token = "123";// tokenHeader.replace(JwtTokenUtils.TOKEN_PREFIX, "");
String username = "admin";// JwtTokenUtils.getUsername(token);
if (username != null)
{
return new UsernamePasswordAuthenticationToken (username, null, new ArrayList<> ());
}
return null;
}
}
package shang.handle;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import shang.entity.JsonMsg;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Auther: Administrator
* @Date: 2021/2/21 19:49
* @Description:这里为了之后结果更直观,自定义一个AuthenticationEntryPoint,
* 用于在未登录是访问接口返回json而不是login.html
* 当未登录或者token失效访问接口时,自定义的返回结果
*/
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint
{
@Override
public void commence(HttpServletRequest httpServletRequest,
HttpServletResponse response, AuthenticationException e) throws IOException, ServletException
{
response.setCharacterEncoding("UTF-8");//设置编码格式
response.setContentType("application/json");
JsonMsg jsonMsg =new JsonMsg ();
jsonMsg.setMsg (" AuthenticationException 【尚未登录,或者登录过期】触发了-->"+e.getMessage());
jsonMsg.setStatusCode (403);
//Jackson
ObjectMapper mapper = new ObjectMapper ();
String msgJson=mapper.writeValueAsString (jsonMsg);
//response.getWriter().println(JSON.toJSONString(Result.error().message("尚未登录,或者登录过期 " + e.getMessage())));
response.getWriter ().print (msgJson);
response.getWriter().flush();
}
}
package shang.handle;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import shang.entity.JsonMsg;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Auther: 三尾鱼
* @Date: 2021/2/19 14:54
* @Description:
*/
public class 登录失败处理器 implements AuthenticationFailureHandler
{
private String url;
public 登录失败处理器(String url)
{
this.url = url;
}
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AuthenticationException e) throws IOException, ServletException
{
//httpServletResponse.sendRedirect (url);
JsonMsg jsonMsg =new JsonMsg ();
jsonMsg.setMsg ("自定义失败处理器 onAuthenticationFailure 触发了");
jsonMsg.setStatusCode (302);
//Jackson
ObjectMapper mapper = new ObjectMapper ();
String msgJson=mapper.writeValueAsString (jsonMsg);
//有中文乱码,设置一下
httpServletResponse.setHeader("Content-type", "application/json;charset=UTF-8");
//OutputStream ps = httpServletResponse.getOutputStream ();
//这句话的意思,使得放入流的数据是utf8格式
//ps.write (personJson.getBytes (StandardCharsets.UTF_8));
httpServletResponse.getWriter ().print (msgJson);
//httpServletResponse.sendRedirect (url);
}
}
package shang.handle;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import shang.entity.JsonMsg;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Auther: 三尾鱼
* @Date: 2021/2/19 14:36
* @Description:
*/
public class 登录成功处理器 implements AuthenticationSuccessHandler
{
private String url;
public 登录成功处理器(String url)
{
this.url = url;
}
/*@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authentication) throws IOException, ServletException
{
}*/
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Authentication authentication) throws IOException, ServletException
{
User user = (User) authentication.getPrincipal ();
System.out.println (user.getUsername ());
System.out.println (user.getPassword ());
System.out.println (user.getAuthorities ());//权限列表,就是UserDetailsServiceImpl放进去的【权限、角色】 数据
System.out.println (httpServletRequest.getRemoteAddr ());
JsonMsg jsonMsg =new JsonMsg ();
jsonMsg.setMsg ("onAuthenticationSuccess 触发了--token:"+"abcd1234admin");
jsonMsg.setStatusCode (200);
//Jackson
ObjectMapper mapper = new ObjectMapper ();
String personJson=mapper.writeValueAsString (jsonMsg);
//有中文乱码,设置一下
httpServletResponse.setHeader("Content-type", "application/json;charset=UTF-8");
//OutputStream ps = httpServletResponse.getOutputStream ();
//这句话的意思,使得输出流的数据是utf8格式
//ps.write (personJson.getBytes (StandardCharsets.UTF_8));
httpServletResponse.getWriter ().print (personJson);
//httpServletResponse.sendRedirect (url);
}
}
package shang.handle;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
/**
* @Auther: 三尾鱼
* @Date: 2021/2/19 17:26
* @Description: 前后端分离的开发 都是要返回JSON
*/
public class 鉴权失败处理器 implements AccessDeniedHandler
{
@Override
public void handle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AccessDeniedException e) throws IOException, ServletException
{
httpServletResponse.setStatus (httpServletResponse.SC_FORBIDDEN);//403
//有中文乱码,设置一下
httpServletResponse.setHeader("Content-type", "application/json;charset=UTF-8");
PrintWriter pw=httpServletResponse.getWriter ();
Map<String,Object> map=new HashMap<String,Object> ();
map.put ("status",403);
map.put ("msg", "权限不够,请联系管理员");
ObjectMapper mapper = new ObjectMapper ();
String JsonStr=mapper.writeValueAsString(map);
pw.write (JsonStr);
//pw.write ("{\"status\":\"error\",\"msg\":\"权限不够,请联系管理员\"} ");
pw.flush ();
pw.close();
}
}
package shang.service;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @Auther: Administrator
* @Date: 2021/2/21 19:37
* @Description:
*/
@Component
public class JwtUtils
{
private static final String CLAIM_KEY_USERNAME = "sub";
private static final String CLAIM_KEY_CREATED = "created";
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
// 创建token
public String generateToken(String username)
{
return Jwts.builder ()
.signWith (SignatureAlgorithm.HS512, secret)
.setSubject (username)
.setIssuedAt (new Date ())
.setExpiration (new Date (System.currentTimeMillis () + expiration * 1000))
.compact ();
}
// 从token中获取用户名
public String getUserNameFromToken(String token)
{
return getTokenBody (token).getSubject ();
}
// 是否已过期
public boolean isExpiration(String token)
{
return getTokenBody (token).getExpiration ().before (new Date ());
}
private Claims getTokenBody(String token)
{
return Jwts.parser ()
.setSigningKey (secret)
.parseClaimsJws (token)
.getBody ();
}
}
package shang.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
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.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
/**
* @Auther: 三尾鱼
* @Date: 2020/11/24 12:20
* @Description:
* USE ipranDB
* GO
* CREATE UNIQUE NONCLUSTERED --唯一 非聚集
* INDEX username_唯一_user on --索引名称
* [ipranDB].[dbo].[user] --表名称
* (username) -- 表的字段名称CREATE UNIQUE NONCLUSTERED --唯一 非聚集
* GO
*
*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService
{
@Autowired
PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username
//username 是前端传递过来的
) throws UsernameNotFoundException
{
System.out.println ("执行了自定义登录逻辑!!");
//这里注入数据库访问类,可以改造成按数据库验证账号和口令
//需要从数据库获取的信息有:1、用户名,2、加密后的口令 3、权限因子或角色
//1、根据用户名到数据库去查询,返回UserDetails的实现类
/*User user;
if (user == null)
{
throw new UsernameNotFoundException ("用户不存在!");
}*/
if(!"admin".equals (username)){
throw new UsernameNotFoundException ("用户不存在!");
}
//2、比较密码(注册时已经加密过),如果匹配成功返回UserDetails,
String password=passwordEncoder.encode("123");
//从数据库获取当前用户的所有角色
//3、这里的user是org.springframework.security.core.userdetails.User 它实现了UserDetails接口
//这里的"admin,normal"是权限因子,如果是角色,必须是【ROLE_】前缀开头,例如 ROLE_admin,ROLE_user
return new User (username, password, AuthorityUtils.commaSeparatedStringToAuthorityList
("admin,normal,ROLE_admin,ROLE_user,/toSuccess,/insert,/delete"));
//user.setRoles (userMapper.getUserRolesByUid (user.getId ()));
//return user;
}
}
package shang.service;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
/**
* @Auther: 三尾鱼
* @Date: 2021/2/20 09:34
* @Description:
*/
@Service
public class MyAccessControImpl implements I自定义权限控制接口
{
//类名,不可写中文,否则配置不进去
@Override
public boolean hasPermission(HttpServletRequest request,
Authentication authentication)
{
Object principal = authentication.getPrincipal ();
if (principal instanceof UserDetails)
{
UserDetails userDetails = (UserDetails) principal;
//获取当前登录用户的授权集合列表
Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities ();
return authorities.contains (new SimpleGrantedAuthority (request.getRequestURI ()));//基于访问URL的权限控制
}
return false;
}
}
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
#指定url,xxx是数据库的名字,serverTimezone=Asia/Shanghai 解决时区问题,&useUnicode=true&characterEncoding=utf-8指定字符的编码集
# jdbc-url: jdbc:mysql://localhost:3306/ipran_db?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
# username: root
# password: aatl?451
url: jdbc:mysql://localhost:3306/ipran_db?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
username: root
password: aatl?451
jwt:
tokenHeader: Authorization #JWT存储的请求头
secret: my-springsecurity-plus #JWT加解密使用的密钥
expiration: 604800 #JWT的超期限时间(60*60*24*7)
tokenHead: 'Bearer ' #JWT负载中拿到开头,空格别忘了