正在显示
11 个修改的文件
包含
154 行增加
和
28 行删除
@@ -172,7 +172,7 @@ | @@ -172,7 +172,7 @@ | ||
172 | 172 | ||
173 | <!--开发环境:打印控制台--> | 173 | <!--开发环境:打印控制台--> |
174 | <springProfile name="dev"> | 174 | <springProfile name="dev"> |
175 | - <logger name="org.springframework.security" level="info"/> | 175 | + <logger name="org.springframework.security" level="trace"/> |
176 | <logger name="org.apache.tomcat" level="info" /> | 176 | <logger name="org.apache.tomcat" level="info" /> |
177 | <logger name="com.tianbo.warehouse.dao" level="DEBUG" /> | 177 | <logger name="com.tianbo.warehouse.dao" level="DEBUG" /> |
178 | <root level="INFO"> | 178 | <root level="INFO"> |
@@ -60,6 +60,15 @@ | @@ -60,6 +60,15 @@ | ||
60 | <artifactId>spring-boot-starter-thymeleaf</artifactId> | 60 | <artifactId>spring-boot-starter-thymeleaf</artifactId> |
61 | </dependency> | 61 | </dependency> |
62 | <dependency> | 62 | <dependency> |
63 | + <groupId>io.jsonwebtoken</groupId> | ||
64 | + <artifactId>jjwt</artifactId> | ||
65 | + <version>0.7.0</version> | ||
66 | + </dependency> | ||
67 | + <dependency> | ||
68 | + <groupId>org.springframework.security</groupId> | ||
69 | + <artifactId>spring-security-jwt</artifactId> | ||
70 | + </dependency> | ||
71 | + <dependency> | ||
63 | <groupId>org.springframework.cloud</groupId> | 72 | <groupId>org.springframework.cloud</groupId> |
64 | <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> | 73 | <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> |
65 | </dependency> | 74 | </dependency> |
@@ -22,6 +22,9 @@ | @@ -22,6 +22,9 @@ | ||
22 | * url角色权限识别 | 22 | * url角色权限识别 |
23 | * menu与权限关联 | 23 | * menu与权限关联 |
24 | * 参数校验 | 24 | * 参数校验 |
25 | +* 集成JWT JAVA Web Token框架 | ||
26 | + * 前后端完全分离 | ||
27 | + * 前端登录验证后,每次访问系统通过在头部携带带有JWT token的Authorization:Bearer "Tokens字符窜"访问系统 | ||
25 | * 已集成mybatis、mybatisGenerator、pageHelper | 28 | * 已集成mybatis、mybatisGenerator、pageHelper |
26 | * 集成定时任务框架 | 29 | * 集成定时任务框架 |
27 | * 目前在IMF框架中使用,打开IMF_Task里面的定时任务注释就可以启动IMF客户端功能 | 30 | * 目前在IMF框架中使用,打开IMF_Task里面的定时任务注释就可以启动IMF客户端功能 |
@@ -51,9 +51,9 @@ public class RequestRequireAOP { | @@ -51,9 +51,9 @@ public class RequestRequireAOP { | ||
51 | 51 | ||
52 | for(int i =0;i<args.length; i++){ | 52 | for(int i =0;i<args.length; i++){ |
53 | //class相等表示是同一个对象 | 53 | //class相等表示是同一个对象 |
54 | - if (args[i].getClass().getName().equals("java.lang.String")) { | 54 | + if (null!=args[i] && args[i].getClass().getName().equals("java.lang.String")) { |
55 | 55 | ||
56 | - if (null==args[i] || ((String)args[i]).isEmpty()){ | 56 | + if (((String)args[i]).isEmpty()){ |
57 | args[i] = null; | 57 | args[i] = null; |
58 | } | 58 | } |
59 | } | 59 | } |
1 | package com.tianbo.warehouse.controller.response; | 1 | package com.tianbo.warehouse.controller.response; |
2 | 2 | ||
3 | +import lombok.Data; | ||
4 | + | ||
3 | import java.io.Serializable; | 5 | import java.io.Serializable; |
4 | 6 | ||
7 | +@Data | ||
5 | public class ResultJson implements Serializable{ | 8 | public class ResultJson implements Serializable{ |
6 | private static final long serialVersionUID = 1L; | 9 | private static final long serialVersionUID = 1L; |
7 | 10 | ||
@@ -11,6 +14,8 @@ public class ResultJson implements Serializable{ | @@ -11,6 +14,8 @@ public class ResultJson implements Serializable{ | ||
11 | private String msg = ""; | 14 | private String msg = ""; |
12 | // 返回对象 | 15 | // 返回对象 |
13 | private Object data = ""; | 16 | private Object data = ""; |
17 | + //返回的JWT | ||
18 | + private String jwtToken; | ||
14 | 19 | ||
15 | public ResultJson() { | 20 | public ResultJson() { |
16 | } | 21 | } |
@@ -33,28 +38,4 @@ public class ResultJson implements Serializable{ | @@ -33,28 +38,4 @@ public class ResultJson implements Serializable{ | ||
33 | this.msg = msg; | 38 | this.msg = msg; |
34 | this.data = data; | 39 | this.data = data; |
35 | } | 40 | } |
36 | - | ||
37 | - public String getCode() { | ||
38 | - return code; | ||
39 | - } | ||
40 | - | ||
41 | - public void setCode(String code) { | ||
42 | - this.code = code; | ||
43 | - } | ||
44 | - | ||
45 | - public String getMsg() { | ||
46 | - return msg; | ||
47 | - } | ||
48 | - | ||
49 | - public void setMsg(String msg) { | ||
50 | - this.msg = msg; | ||
51 | - } | ||
52 | - | ||
53 | - public Object getData() { | ||
54 | - return data; | ||
55 | - } | ||
56 | - | ||
57 | - public void setData(Object data) { | ||
58 | - this.data = data; | ||
59 | - } | ||
60 | } | 41 | } |
@@ -31,7 +31,6 @@ public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor imp | @@ -31,7 +31,6 @@ public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor imp | ||
31 | 31 | ||
32 | @Override | 32 | @Override |
33 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { | 33 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { |
34 | - | ||
35 | FilterInvocation fi = new FilterInvocation(request, response, chain); | 34 | FilterInvocation fi = new FilterInvocation(request, response, chain); |
36 | invoke(fi); | 35 | invoke(fi); |
37 | } | 36 | } |
@@ -2,6 +2,7 @@ package com.tianbo.warehouse.security.config; | @@ -2,6 +2,7 @@ package com.tianbo.warehouse.security.config; | ||
2 | 2 | ||
3 | import com.netflix.discovery.converters.Auto; | 3 | import com.netflix.discovery.converters.Auto; |
4 | import com.tianbo.warehouse.security.CustomUserDetailService; | 4 | import com.tianbo.warehouse.security.CustomUserDetailService; |
5 | +import com.tianbo.warehouse.security.filter.JwtAuthenticationTokenFilter; | ||
5 | import com.tianbo.warehouse.security.handel.*; | 6 | import com.tianbo.warehouse.security.handel.*; |
6 | import com.tianbo.warehouse.security.MyFilterSecurityInterceptor; | 7 | import com.tianbo.warehouse.security.MyFilterSecurityInterceptor; |
7 | import org.springframework.beans.factory.annotation.Autowired; | 8 | import org.springframework.beans.factory.annotation.Autowired; |
@@ -14,9 +15,11 @@ import org.springframework.security.config.annotation.method.configuration.Enabl | @@ -14,9 +15,11 @@ import org.springframework.security.config.annotation.method.configuration.Enabl | ||
14 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; | 15 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
15 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | 16 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
16 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | 17 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; |
18 | +import org.springframework.security.config.http.SessionCreationPolicy; | ||
17 | import org.springframework.security.core.userdetails.UserDetailsService; | 19 | import org.springframework.security.core.userdetails.UserDetailsService; |
18 | import org.springframework.security.crypto.password.PasswordEncoder; | 20 | import org.springframework.security.crypto.password.PasswordEncoder; |
19 | import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; | 21 | import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; |
22 | +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||
20 | import org.springframework.web.cors.CorsUtils; | 23 | import org.springframework.web.cors.CorsUtils; |
21 | 24 | ||
22 | @Configuration | 25 | @Configuration |
@@ -50,6 +53,9 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | @@ -50,6 +53,9 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | ||
50 | @Autowired | 53 | @Autowired |
51 | private MyAuthenticationEntryPoint authenticationEntryPoint; | 54 | private MyAuthenticationEntryPoint authenticationEntryPoint; |
52 | 55 | ||
56 | + @Autowired | ||
57 | + private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; | ||
58 | + | ||
53 | @Override | 59 | @Override |
54 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { | 60 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
55 | //user Details Service验证 | 61 | //user Details Service验证 |
@@ -109,7 +115,17 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | @@ -109,7 +115,17 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | ||
109 | .and() | 115 | .and() |
110 | .csrf().disable(); | 116 | .csrf().disable(); |
111 | 117 | ||
118 | + | ||
112 | http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class); | 119 | http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class); |
120 | + /** | ||
121 | + * 配合JWT做的配置,前后端完全分离,前端与后端不在一台服务器上的配置 | ||
122 | + */ | ||
123 | + http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); | ||
124 | + // 禁用headers缓存 | ||
125 | + http.headers().cacheControl(); | ||
126 | + //关闭session | ||
127 | + http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); | ||
128 | + | ||
113 | 129 | ||
114 | //session管理 | 130 | //session管理 |
115 | //session失效后跳转 | 131 | //session失效后跳转 |
1 | +package com.tianbo.warehouse.security.filter; | ||
2 | + | ||
3 | +import com.tianbo.warehouse.security.CustomUserDetailService; | ||
4 | +import org.springframework.beans.factory.annotation.Autowired; | ||
5 | +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
6 | +import org.springframework.security.core.context.SecurityContextHolder; | ||
7 | +import org.springframework.security.core.userdetails.UserDetails; | ||
8 | +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; | ||
9 | +import org.springframework.stereotype.Component; | ||
10 | +import org.springframework.web.filter.OncePerRequestFilter; | ||
11 | + | ||
12 | +import javax.servlet.FilterChain; | ||
13 | +import javax.servlet.ServletException; | ||
14 | +import javax.servlet.ServletRequest; | ||
15 | +import javax.servlet.ServletResponse; | ||
16 | +import javax.servlet.http.HttpServletRequest; | ||
17 | +import javax.servlet.http.HttpServletResponse; | ||
18 | +import java.io.IOException; | ||
19 | + | ||
20 | +/** | ||
21 | + * 访问时判定JAVA WEB TOKEN,是否有TOKEN,有TOKEN是否超时, | ||
22 | + * 正常则取出TOKEN ,从TOKEN中获取用户名,赋予系统登录。 | ||
23 | + * 注意此过滤器每次都会被访问,每个URL带TOKEN 访问这里然后去查用户的资料 会造成数据库压力。 | ||
24 | + * !!!!后期要把用户资料存储在Redis中,然后用户资料从redis中取,减少数据库压力。 | ||
25 | + */ | ||
26 | +@Component | ||
27 | +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter{ | ||
28 | + | ||
29 | + @Autowired | ||
30 | + CustomUserDetailService userDetailService; | ||
31 | + | ||
32 | + @Override | ||
33 | + protected void doFilterInternal( | ||
34 | + HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) | ||
35 | + throws ServletException, IOException{ | ||
36 | + | ||
37 | + //请求头为 Authorization | ||
38 | + //请求体为 Bearer token | ||
39 | + String authHeader = request.getHeader("Authorization"); | ||
40 | + if (authHeader != null && authHeader.startsWith("Bearer ")) { | ||
41 | + final String authToken = authHeader.substring("Bearer ".length()); | ||
42 | + | ||
43 | + String username = JwtTokenUtil.parseToken(authToken); | ||
44 | + | ||
45 | + //有JWT 没有登录,去JWT的 信息 获取用户信息,赋予登录 | ||
46 | + if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { | ||
47 | + UserDetails userDetails = userDetailService.loadUserByUsername(username); | ||
48 | + if (userDetails != null) { | ||
49 | + | ||
50 | + UsernamePasswordAuthenticationToken authentication = | ||
51 | + new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities()); | ||
52 | + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); | ||
53 | + SecurityContextHolder.getContext().setAuthentication(authentication); | ||
54 | + } | ||
55 | + } | ||
56 | + | ||
57 | + } | ||
58 | + filterChain.doFilter(request, response); | ||
59 | + } | ||
60 | +} |
1 | +package com.tianbo.warehouse.security.filter; | ||
2 | + | ||
3 | +import io.jsonwebtoken.Claims; | ||
4 | +import io.jsonwebtoken.Jwts; | ||
5 | +import io.jsonwebtoken.SignatureAlgorithm; | ||
6 | + | ||
7 | +import java.io.InputStream; | ||
8 | +import java.security.KeyStore; | ||
9 | +import java.security.PrivateKey; | ||
10 | +import java.security.PublicKey; | ||
11 | +import java.util.Date; | ||
12 | + | ||
13 | +public class JwtTokenUtil { | ||
14 | + //加载jwt.jks文件 | ||
15 | + private static InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("jwt.jks"); | ||
16 | + private static PrivateKey privateKey = null; | ||
17 | + private static PublicKey publicKey = null; | ||
18 | + | ||
19 | + static { | ||
20 | + try { | ||
21 | + KeyStore keyStore = KeyStore.getInstance("JKS"); | ||
22 | + keyStore.load(inputStream, "vmvnv1v2".toCharArray()); | ||
23 | + privateKey = (PrivateKey) keyStore.getKey("jwt", "vmvnv1v2".toCharArray()); | ||
24 | + publicKey = keyStore.getCertificate("jwt").getPublicKey(); | ||
25 | + } catch (Exception e) { | ||
26 | + e.printStackTrace(); | ||
27 | + } | ||
28 | + } | ||
29 | + | ||
30 | + public static String generateToken(String subject, int expirationSeconds) { | ||
31 | + return Jwts.builder() | ||
32 | + .setClaims(null) | ||
33 | + .setSubject(subject) | ||
34 | + .setExpiration(new Date(System.currentTimeMillis() + expirationSeconds * 1000)) | ||
35 | + .signWith(SignatureAlgorithm.RS256, privateKey) | ||
36 | + .compact(); | ||
37 | + } | ||
38 | + | ||
39 | + public static String parseToken(String token) { | ||
40 | + String subject = null; | ||
41 | + try { | ||
42 | + Claims claims = Jwts.parser() | ||
43 | + .setSigningKey(publicKey) | ||
44 | + .parseClaimsJws(token).getBody(); | ||
45 | + subject = claims.getSubject(); | ||
46 | + } catch (Exception e) { | ||
47 | + } | ||
48 | + return subject; | ||
49 | + } | ||
50 | +} |
@@ -5,6 +5,7 @@ import com.tianbo.warehouse.bean.AuthSuccessResponse; | @@ -5,6 +5,7 @@ import com.tianbo.warehouse.bean.AuthSuccessResponse; | ||
5 | import com.tianbo.warehouse.controller.PermssionController; | 5 | import com.tianbo.warehouse.controller.PermssionController; |
6 | import com.tianbo.warehouse.model.PERMISSION; | 6 | import com.tianbo.warehouse.model.PERMISSION; |
7 | import com.tianbo.warehouse.model.USERS; | 7 | import com.tianbo.warehouse.model.USERS; |
8 | +import com.tianbo.warehouse.security.filter.JwtTokenUtil; | ||
8 | import com.tianbo.warehouse.security.model.LoginType; | 9 | import com.tianbo.warehouse.security.model.LoginType; |
9 | import com.tianbo.warehouse.service.PermissionService; | 10 | import com.tianbo.warehouse.service.PermissionService; |
10 | import org.apache.commons.logging.Log; | 11 | import org.apache.commons.logging.Log; |
@@ -50,9 +51,16 @@ public class MyAuthenticationSuccessHandler extends SavedRequestAwareAuthenticat | @@ -50,9 +51,16 @@ public class MyAuthenticationSuccessHandler extends SavedRequestAwareAuthenticat | ||
50 | //将 authention 信息打包成json格式返回 | 51 | //将 authention 信息打包成json格式返回 |
51 | response.setContentType("application/json;charset=UTF-8"); | 52 | response.setContentType("application/json;charset=UTF-8"); |
52 | response.setHeader("Access-Control-Allow-Origin","*"); | 53 | response.setHeader("Access-Control-Allow-Origin","*"); |
54 | + | ||
55 | + | ||
53 | USERS loginedUser = (USERS) authentication.getPrincipal(); | 56 | USERS loginedUser = (USERS) authentication.getPrincipal(); |
54 | //返回前端的数据安全起见把password去掉 | 57 | //返回前端的数据安全起见把password去掉 |
55 | loginedUser.setPassword(null); | 58 | loginedUser.setPassword(null); |
59 | + | ||
60 | + //设置用户的TOKEN的有效时间,下面是300秒=5分钟 | ||
61 | + String jwtToken = JwtTokenUtil.generateToken(loginedUser.getUsername(), 300); | ||
62 | + response.setHeader("Authorization",jwtToken); | ||
63 | + | ||
56 | Map<String,Object> menuMap = permissionService.getUserMenus(loginedUser.getUserId()); | 64 | Map<String,Object> menuMap = permissionService.getUserMenus(loginedUser.getUserId()); |
57 | response.getWriter().write(objectMapper.writeValueAsString(new AuthSuccessResponse(authentication,menuMap))); | 65 | response.getWriter().write(objectMapper.writeValueAsString(new AuthSuccessResponse(authentication,menuMap))); |
58 | }else { | 66 | }else { |
src/main/resources/jwt.jks
0 → 100644
不能预览此文件类型
-
请 注册 或 登录 后发表评论