引入jar
这里只是spring security + jwt 的包
<!--核心-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>
<!--配置-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>
<!--JWT-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
WebSecurityConfig
package com.os.common.config.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JWTAuthenticationFilter jwtAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
// 设置登录信息
http.formLogin()
.loginPage(SecurityConst.LOGIN_URL)
.and()
// 设置拦截信息
.authorizeRequests()
.antMatchers(SecurityConst.PERMIT_URL).permitAll()
.antMatchers("/api/user/get").hasAuthority("USER")
.anyRequest().authenticated()
.and()
// 关闭session 与csrf
.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// 禁用缓存
http.headers().cacheControl();
// 添加自定义拦截器
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
}
JWTAuthenticationFilter 自定义过滤器验证jwt
package com.os.common.config.security;
import com.os.core.utils.web.WebUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
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;
/**
* JWT验证过滤器
*
* @author Peng
*/
@Component
public class JWTAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
// 判断路径是否是过滤路径
if (ArrayUtils.contains(SecurityConst.PERMIT_URL, request.getRequestURI())) {
chain.doFilter(request, response);
return;
}
String jwt = WebUtils.getCookie(request, JWTUserDetailsUtils.COOKIE_KEY);
if (jwt == null || jwt.equals("")) {
response.sendRedirect(SecurityConst.LOGIN_URL);
return;
}
UserDetails userDetails = JWTUserDetailsUtils.getUserDetailsByToken(jwt);
if (userDetails == null) {
response.sendRedirect(SecurityConst.LOGIN_URL);
return;
}
if (SecurityContextHolder.getContext().getAuthentication() == null) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
}
}
JWTUserDetailsUtils jwt-token工具类
package com.os.common.config.security;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Date;
/**
* jwt-token工具类
*
* @author Peng
*/
public class JWTUserDetailsUtils {
/**
* 私钥
*/
private static final String PRIVATE_KEY = "123456789";
private static final String KEY = "ACCOUNT";
/**
* 客户端cookies name
*/
public static final String COOKIE_KEY = "token";
/**
* 获取UserDetails
*
* @param token 客户端token
* @return UserDetails
*/
public static UserDetails getUserDetailsByToken(String token) {
User user;
try {
Claims claims = Jwts.parser()
.setSigningKey(PRIVATE_KEY)
.parseClaimsJws(token)
.getBody();
String account = claims.get(KEY, String.class);
user = new User(account, "", true,
true,
true,
true,
AuthorityUtils.commaSeparatedStringToAuthorityList("USER"));
} catch (Exception e) {
user = null;
}
return user;
}
/**
* 获取JWT
*
* @param exp 过期时间
* @param account 账号
* @return JWT
*/
public static String getJwtToken(Date exp, String account) {
String jwt = Jwts.builder()
.signWith(SignatureAlgorithm.HS256, PRIVATE_KEY)
.setExpiration(exp)
.claim(KEY, account)
.compact();
return jwt;
}
}
SecurityConst 一些允许访问的常量
package com.os.common.config.security;
/**
* 常量
*
* @author Peng
*/
public class SecurityConst {
/**
* 允许访问的url
*/
public static final String[] PERMIT_URL = {"/api/loginForm", "/api/login", "/static/*", "/api/codeImg"};
/**
* 登录url
*/
public static final String LOGIN_URL = "/api/login";
}
登录Controller
package com.os.program.controller;
import com.os.common.config.security.JWTUserDetailsUtils;
import com.os.core.utils.web.WebUtils;
import org.joda.time.DateTime;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
/**
* 登录页面
*
* @author Peng
*/
@Controller
public class LoginController {
public final static String LOGIN_CODE_NAME = "LOGIN_CODE_NAME";
@RequestMapping("/api/login")
public String goLogin(HttpServletRequest request, HttpServletResponse response) {
return "pages/login";
}
/**
* 登录处理
*
* @param username 账号
* @param password 密码
*/
@RequestMapping("/api/loginForm")
public String loginForm(HttpServletResponse response, @RequestParam("username") String username, @RequestParam("password") String password) {
// 这里写死了 正常情况应该去数据库验证
if (username.equals("123456") && password.equals("123456")) {
String value = JWTUserDetailsUtils.getJwtToken(DateTime.now().plusDays(1).toDate(), username);
// cookie保存一天
WebUtils.setCookie(response, JWTUserDetailsUtils.COOKIE_KEY, value, 1);
return "redirect:/";
} else {
return "redirect:" + SecurityConst.LOGIN_URL;
}
}
}