security实现加密和匹配密码
导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
引入依赖后会默认拦截所有路径的请求,可新建一个配置类进行配置,下面的配置适用于仅使用security的加密功能
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//authorizeRequests所有security全注解配置实现的开端,表示开始说明需要的权限。
//需要的权限分两部分,第一部分是拦截的路径,第二部分访问该路径需要的权限。
//antMatchers表示拦截什么路径,permitAll任何权限都可以访问,直接放行所有。
//anyRequest()任何的请求,authenticated认证后才能访问
//.and().csrf().disable();固定写法,表示使csrf拦截失效。
//此配置适用于仅使用security的加密,不使用它的拦截功能
http
.authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and().csrf().disable();
}
}
在启动类里注入bean
@Bean
public BCryptPasswordEncoder encoder(){
return new BCryptPasswordEncoder();
}
在service层注入
@Autowired
private BCryptPasswordEncoder encoder;
密码加密,此代码为示例,参数是未加密的password
user.setPassword(encoder.encode(password));
匹配密码,第一个参数是用户输入的密码,第二个是加密的密码,匹配成功返回true,失败false
encoder.matches(password,user.getPassword())
jwt和token认证
引入依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.6.0</version>
</dependency>
在启动类中注入
@Bean
@ConfigurationProperties("jwt.config")
public JwtUtil jwtUtil(){
return new JwtUtil();
}
创建jwt工具类
public class JwtUtil {
private String key ;
private long ttl ;//一个小时
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public long getTtl() {
return ttl;
}
public void setTtl(long ttl) {
this.ttl = ttl;
}
/**
* 生成JWT
*
* @param id
* @param subject
* @return
*/
public String createJWT(String id, String subject, String roles) {
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
JwtBuilder builder = Jwts.builder().setId(id)
.setSubject(subject)
.setIssuedAt(now)
.signWith(SignatureAlgorithm.HS256, key).claim("roles", roles);
if (ttl > 0) {
builder.setExpiration( new Date( nowMillis + ttl));
}
return builder.compact();
}
/**
* 解析JWT
* @param jwtStr
* @return
*/
public Claims parseJWT(String jwtStr){
return Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(jwtStr)
.getBody();
}
}
在配置文件中配置盐和过期时间
jwt:
config:
key: itcast
ttl: 3600000
登录成功后生成token
String token = jwtUtil.createJWT(adminLogin.getId(), adminLogin.getLoginname(), "admin");
Map<String,Object> map =new HashMap<>();
map.put("token",token);
map.put("role","admin");
创建一个拦截器,拦截器只是负责把有请求头中包含token的令牌进行一个解析验证
@Component
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
private JwtUtil jwtUtil;
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("经过了拦截器");
//无论如何都放行。具体能不能操作还是在具体的操作中去判断。
//拦截器只是负责把有请求头中包含token的令牌进行一个解析验证。
String header = request.getHeader("Authorization");
if(header!=null && !"".equals(header)){
//如果有包含有Authorization头信息,就对其进行解析
if(header.startsWith("Bearer ")){
//得到token
String token = header.substring(7);
//对令牌进行验证
try {
Claims claims = jwtUtil.parseJWT(token);
String roles = (String) claims.get("roles");
if(roles!=null && roles.equals("admin")){
request.setAttribute("claims_admin", token);
}
if(roles!=null && roles.equals("user")){
request.setAttribute("claims_user", token);
}
}catch (Exception e){
throw new RuntimeException("令牌不正确!");
}
}
}
return true;
}
}
配置拦截器
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
@Autowired
private JwtInterceptor jwtInterceptor;
protected void addInterceptors(InterceptorRegistry registry) {
//注册拦截器要声明拦截器对象和要拦截的请求
registry.addInterceptor(jwtInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/**/login/**");
}
}
在需要登录权限的地方获取token
String token = (String) request.getAttribute("claims_admin");
if(token == null || "".equals(token)){
throw new RuntimeException("权限不足!");
}