Browse Source

fix shiro filter

张延森 3 years ago
parent
commit
f49585223c

+ 2
- 2
src/main/java/com/yunzhi/nanyang/controller/LoginController.java View File

86
 
86
 
87
     @GetMapping("/401")
87
     @GetMapping("/401")
88
     @ApiOperation(value="401无权限", notes = "401无权限", httpMethod = "GET", response = ResponseBean.class)
88
     @ApiOperation(value="401无权限", notes = "401无权限", httpMethod = "GET", response = ResponseBean.class)
89
-    public ResponseBean unAuth() throws Exception {
90
-        return ResponseBean.error("未登录或暂无权限", ResponseBean.ERROR_AUTH_FAIL);
89
+    public ResponseBean unAuth(@RequestParam(value = "msg", defaultValue = "未登录或暂无权限") String msg) throws Exception {
90
+        return ResponseBean.error(msg, ResponseBean.ERROR_AUTH_FAIL);
91
     }
91
     }
92
 
92
 
93
 //    @PutMapping("/admin/change-password")
93
 //    @PutMapping("/admin/change-password")

+ 25
- 5
src/main/java/com/yunzhi/nanyang/shiro/filters/JWTFilter.java View File

2
 
2
 
3
 import com.yunzhi.nanyang.shiro.utils.JWTToken;
3
 import com.yunzhi.nanyang.shiro.utils.JWTToken;
4
 import com.yunzhi.nanyang.shiro.utils.JWTUtil;
4
 import com.yunzhi.nanyang.shiro.utils.JWTUtil;
5
+import org.apache.shiro.authc.AuthenticationException;
5
 import org.apache.shiro.authc.AuthenticationToken;
6
 import org.apache.shiro.authc.AuthenticationToken;
6
 import org.apache.shiro.subject.Subject;
7
 import org.apache.shiro.subject.Subject;
7
 import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
8
 import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
13
 import javax.servlet.ServletResponse;
14
 import javax.servlet.ServletResponse;
14
 import javax.servlet.http.HttpServletResponse;
15
 import javax.servlet.http.HttpServletResponse;
15
 import java.io.IOException;
16
 import java.io.IOException;
17
+import java.io.UnsupportedEncodingException;
18
+import java.net.URLEncoder;
16
 
19
 
17
 public class JWTFilter extends AuthenticatingFilter {
20
 public class JWTFilter extends AuthenticatingFilter {
18
 
21
 
38
         return new JWTToken(authorization);
41
         return new JWTToken(authorization);
39
     }
42
     }
40
 
43
 
44
+    @Override
45
+    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
46
+        AuthenticationToken token = this.createToken(request, response);
47
+        Subject subject = this.getSubject(request, response);
48
+        subject.login(token);
49
+        return this.onLoginSuccess(token, subject, request, response);
50
+    }
51
+
41
     @Override
52
     @Override
42
     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
53
     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
43
         boolean allowed = false;
54
         boolean allowed = false;
44
         try {
55
         try {
45
             allowed = executeLogin(request, response);
56
             allowed = executeLogin(request, response);
46
         } catch (Exception e) {
57
         } catch (Exception e) {
47
-            response401(request, response);
58
+            response401(request, response, e);
48
         }
59
         }
49
 
60
 
50
         return allowed;
61
         return allowed;
73
     /**
84
     /**
74
      *Jump illegal request to / 401
85
      *Jump illegal request to / 401
75
      */
86
      */
76
-    private void response401(ServletRequest request, ServletResponse response) {
87
+    private void response401(ServletRequest request, ServletResponse response, Exception e) {
88
+        String message = "";
89
+        if (e != null) {
90
+            try {
91
+                message = URLEncoder.encode(e.getMessage(), "UTF-8");
92
+            } catch (UnsupportedEncodingException ex) {
93
+                //
94
+            }
95
+        }
96
+
77
         try {
97
         try {
78
-            WebUtils.toHttp(response).sendRedirect(unauthorizedUrl);
79
-        } catch (IOException e) {
80
-            LOGGER.error(e.getMessage());
98
+            WebUtils.toHttp(response).sendRedirect(unauthorizedUrl + "?msg=" + message);
99
+        } catch (IOException e1) {
100
+            LOGGER.error(e1.getMessage());
81
         }
101
         }
82
     }
102
     }
83
 }
103
 }

+ 5
- 3
src/main/java/com/yunzhi/nanyang/shiro/matcher/JWTCredentialsMatcher.java View File

1
 package com.yunzhi.nanyang.shiro.matcher;
1
 package com.yunzhi.nanyang.shiro.matcher;
2
 
2
 
3
-import com.yunzhi.nanyang.shiro.utils.JWTUtil;
4
 import org.apache.shiro.authc.AuthenticationInfo;
3
 import org.apache.shiro.authc.AuthenticationInfo;
5
 import org.apache.shiro.authc.AuthenticationToken;
4
 import org.apache.shiro.authc.AuthenticationToken;
6
 import org.apache.shiro.authc.credential.CredentialsMatcher;
5
 import org.apache.shiro.authc.credential.CredentialsMatcher;
8
 public class JWTCredentialsMatcher implements CredentialsMatcher {
7
 public class JWTCredentialsMatcher implements CredentialsMatcher {
9
     @Override
8
     @Override
10
     public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
9
     public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
11
-        String token = authenticationToken.getCredentials().toString();
12
-        return JWTUtil.verify(token);
10
+//        String token = authenticationToken.getCredentials().toString();
11
+//        return JWTUtil.verify(token);
12
+
13
+        // 校验在 realm 做过了
14
+        return true;
13
     }
15
     }
14
 }
16
 }

+ 18
- 5
src/main/java/com/yunzhi/nanyang/shiro/realms/manager/ManagerRealm.java View File

1
 package com.yunzhi.nanyang.shiro.realms.manager;
1
 package com.yunzhi.nanyang.shiro.realms.manager;
2
 
2
 
3
+import com.auth0.jwt.exceptions.JWTDecodeException;
4
+import com.auth0.jwt.exceptions.TokenExpiredException;
3
 import com.yunzhi.nanyang.shiro.utils.JWTToken;
5
 import com.yunzhi.nanyang.shiro.utils.JWTToken;
4
 import com.yunzhi.nanyang.shiro.utils.JWTUtil;
6
 import com.yunzhi.nanyang.shiro.utils.JWTUtil;
5
-import org.apache.shiro.authc.AuthenticationException;
6
-import org.apache.shiro.authc.AuthenticationInfo;
7
-import org.apache.shiro.authc.AuthenticationToken;
8
-import org.apache.shiro.authc.SimpleAuthenticationInfo;
7
+import org.apache.shiro.authc.*;
9
 import org.apache.shiro.authz.AuthorizationInfo;
8
 import org.apache.shiro.authz.AuthorizationInfo;
10
 import org.apache.shiro.authz.SimpleAuthorizationInfo;
9
 import org.apache.shiro.authz.SimpleAuthorizationInfo;
11
 import org.apache.shiro.realm.AuthorizingRealm;
10
 import org.apache.shiro.realm.AuthorizingRealm;
43
     @Override
42
     @Override
44
     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
43
     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
45
         String token = (String) authenticationToken.getPrincipal();
44
         String token = (String) authenticationToken.getPrincipal();
45
+
46
+        // 这里进行 token 验证, CredentialsMatcher 就不做了
47
+        try {
48
+            JWTUtil.verify(token);
49
+        } catch (JWTDecodeException e1) {
50
+            throw new AuthenticationException("非法的权限凭证");
51
+        } catch (TokenExpiredException e2) {
52
+            throw new ExpiredCredentialsException("授权过期, 请重新登录");
53
+        } catch (Exception e) {
54
+            e.printStackTrace();
55
+            throw new AuthenticationException("凭证校验失败, 请重新登录");
56
+        }
57
+
58
+
46
         String loginId = JWTUtil.getLoginId(token);
59
         String loginId = JWTUtil.getLoginId(token);
47
 
60
 
48
         if (!iManagerService.verify(loginId)) {
61
         if (!iManagerService.verify(loginId)) {
49
-            throw new AuthenticationException("User is abnormal");
62
+            throw new LockedAccountException("用户不存在或者状态异常");
50
         }
63
         }
51
 
64
 
52
         // 交给 AuthenticatingRealm 使用 CredentialsMatcher 行校验
65
         // 交给 AuthenticatingRealm 使用 CredentialsMatcher 行校验

+ 9
- 8
src/main/java/com/yunzhi/nanyang/shiro/utils/JWTUtil.java View File

3
 import com.auth0.jwt.JWT;
3
 import com.auth0.jwt.JWT;
4
 import com.auth0.jwt.algorithms.Algorithm;
4
 import com.auth0.jwt.algorithms.Algorithm;
5
 import com.auth0.jwt.exceptions.JWTDecodeException;
5
 import com.auth0.jwt.exceptions.JWTDecodeException;
6
+import com.auth0.jwt.exceptions.JWTVerificationException;
6
 import com.auth0.jwt.interfaces.DecodedJWT;
7
 import com.auth0.jwt.interfaces.DecodedJWT;
8
+import com.auth0.jwt.interfaces.JWTVerifier;
7
 
9
 
8
 import java.util.Date;
10
 import java.util.Date;
9
 
11
 
52
         return sign(loginId, secret);
54
         return sign(loginId, secret);
53
     }
55
     }
54
 
56
 
55
-    public static boolean verify(String token) {
56
-        try {
57
-            JWT.decode(token);
58
-            return true;
59
-        } catch (Exception e) {
60
-            e.printStackTrace();
61
-            return false;
62
-        }
57
+    public static void verify(String token) throws JWTVerificationException {
58
+        DecodedJWT jwt = JWT.decode(token);
59
+        String loginId = jwt.getSubject();
60
+        String secret = jwt.getClaim("secret").asString();
61
+        Algorithm algorithm = Algorithm.HMAC256(secret);
62
+        JWTVerifier verifier = JWT.require(algorithm).withSubject(loginId).build();
63
+        verifier.verify(jwt);
63
     }
64
     }
64
 
65
 
65
 }
66
 }