taizhimin před 5 roky
rodič
revize
3e7be0149a

+ 5 - 0
sys/pom.xml

@@ -19,6 +19,11 @@
             <artifactId>shiro-spring</artifactId>
             <version>1.4.0</version>
         </dependency>
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.6.0</version>
+        </dependency>
     </dependencies>
 
 

+ 39 - 0
sys/src/main/java/com/rxida/xilinedu/sys/common/JWTFilter.java

@@ -0,0 +1,39 @@
+package com.rxida.xilinedu.sys.common;
+
+import org.apache.shiro.authz.UnauthorizedException;
+import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+public class JWTFilter extends BasicHttpAuthenticationFilter {
+    @Override
+    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws UnauthorizedException {
+        //判断请求的请求头是否带上 "Token"
+        if (((HttpServletRequest) request).getHeader("X-Token") != null) {
+            //如果存在,则进入 executeLogin 方法执行登入,检查 token 是否正确
+            try {
+                executeLogin(request, response);
+                return true;
+            } catch (Exception e) {
+                //token 错误
+                // responseError(response, e.getMessage());
+                throw new RuntimeException("token 错误");
+            }
+        }
+        //如果请求头不存在 Token,则可能是执行登陆操作或者是游客状态访问,无需检查 token,直接返回 true
+        return true;
+    }
+
+    @Override
+    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
+        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+        String token = httpServletRequest.getHeader("X-Token");
+        JWTToken jwtToken = new JWTToken(token);
+        // 提交给realm进行登入,如果错误他会抛出异常并被捕获
+        getSubject(request, response).login(jwtToken);
+        // 如果没有抛出异常则代表登入成功,返回true
+        return true;
+    }
+}

+ 12 - 0
sys/src/main/java/com/rxida/xilinedu/sys/common/JWTToken.java

@@ -0,0 +1,12 @@
+package com.rxida.xilinedu.sys.common;
+
+import org.apache.shiro.authc.UsernamePasswordToken;
+
+public class JWTToken extends UsernamePasswordToken {
+    String token;
+
+    JWTToken(String token) {
+        super();
+        this.token = token;
+    }
+}

+ 20 - 0
sys/src/main/java/com/rxida/xilinedu/sys/common/JWTUtil.java

@@ -0,0 +1,20 @@
+package com.rxida.xilinedu.sys.common;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+
+import java.util.Date;
+
+public class JWTUtil {
+    static long EXPIRE_TIME = 10000;
+    static String SECRET = "Rxida@2019";
+
+    public static JWTToken create(String username) {
+        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
+        Algorithm algorithm = Algorithm.HMAC256(SECRET);
+        String username1 = JWT.create().withClaim("username", username)//到期时间
+                .withExpiresAt(date) //创建一个新的JWT,并使用给定的算法进行标记
+                .sign(algorithm);
+        return new JWTToken(username1);
+    }
+}

+ 6 - 5
sys/src/main/java/com/rxida/xilinedu/sys/common/ShiroConfiguration.java

@@ -16,11 +16,12 @@ import java.util.Map;
 public class ShiroConfiguration {
 
     //Filter工厂,设置对应的过滤条件和跳转条件
-    @Bean(name="shiroFilter")
+    @Bean(name = "shiroFilter")
     public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
         ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
         shiroFilterFactoryBean.setSecurityManager(securityManager);
         Map<String, String> map = new HashMap<String, String>();
+        map.put("jwt", new JWTFilter());
         //登出
         map.put("/logout", "logout");
         //对所有用户认证
@@ -36,7 +37,7 @@ public class ShiroConfiguration {
     }
 
     //配置核心安全事务管理器
-    @Bean(name="securityManager")
+    @Bean(name = "securityManager")
     public SecurityManager securityManager() {
         DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
         securityManager.setRealm(systemAuthorizingRealm());
@@ -44,7 +45,7 @@ public class ShiroConfiguration {
     }
 
     //将自己的验证方式加入容器
-    @Bean(name="systemAuthorizingRealm")
+    @Bean(name = "systemAuthorizingRealm")
     public SystemAuthorizingRealm systemAuthorizingRealm() {
         SystemAuthorizingRealm systemAuthorizingRealm = new SystemAuthorizingRealm();
         systemAuthorizingRealm.setCredentialsMatcher(hashedCredentialsMatcher());
@@ -52,7 +53,7 @@ public class ShiroConfiguration {
     }
 
     @Bean
-    public HashedCredentialsMatcher hashedCredentialsMatcher(){
+    public HashedCredentialsMatcher hashedCredentialsMatcher() {
         HashedCredentialsMatcher matcher = new HashedCredentialsMatcher("SHA-1");
         matcher.setHashIterations(1024);
         return matcher;
@@ -60,7 +61,7 @@ public class ShiroConfiguration {
 
     // AOP式方法级权限检查
     @Bean
-    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
+    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
         DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
         creator.setProxyTargetClass(true);
         return creator;

+ 7 - 10
sys/src/main/java/com/rxida/xilinedu/sys/common/SystemAuthorizingRealm.java

@@ -17,18 +17,12 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
+
 @Component("authorizer")
 public class SystemAuthorizingRealm extends AuthorizingRealm {
     @Resource
     private UserDao userDao;
 
-    //告诉shiro如何根据获取到的用户信息中的密码和盐值来校验密码
-    {
-        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher("SHA-1");
-        matcher.setHashIterations(1024);
-        this.setCredentialsMatcher(matcher);
-    }
-
     public SystemAuthorizingRealm() {
         this.setCachingEnabled(false);
     }
@@ -61,13 +55,16 @@ public class SystemAuthorizingRealm extends AuthorizingRealm {
             return null;
         }
         //获取用户信息
-        String username = (String) authenticationToken.getPrincipal();
-        User user = userDao.findByUsername(username);
+        User u = (User) authenticationToken.getPrincipal();
+        User user = userDao.findByUsername(u.getUsername());
         if (user == null) {
             //这里返回后会报出对应异常
             return null;
         } else {
-
+            final JWTToken authenticationToken1 = (JWTToken) authenticationToken;
+            if (user.getUsername() == null || !JWTUtil.verify(authenticationToken1, user.getUsername())) {
+                throw new AuthenticationException("token认证失败!");
+            }
             byte[] salt = Encodes.decodeHex(user.getPassword().substring(0, 16));
             return new SimpleAuthenticationInfo(
                     user,

+ 3 - 3
sys/src/main/resources/mapper/sys/UserDao.xml

@@ -34,9 +34,9 @@
         LEFT JOIN sys_role sr ON sr.id = sur.role_id
         LEFT JOIN sys_role_menu  srm ON srm.role_id = sr.id
         LEFT JOIN sys_menu  sm ON sm.id = srm.menu_id
-        WHERE login_name = #{username}
+        WHERE a.login_name = #{username}
     </select>
-    <select id="get" parameterType="com.rxida.xilinedu.sys.entity.User" resultMap="userResult">
+    <select id="get" resultMap="userResult">
         select
           a.id AS "id",
           a.name AS "name",
@@ -53,7 +53,7 @@
         LEFT JOIN sys_role sr ON sr.id = sur.role_id
         LEFT JOIN sys_role_menu  srm ON srm.role_id = sr.id
         LEFT JOIN sys_menu  sm ON sm.id = srm.menu_id
-        WHERE id = #{id}
+        WHERE a.id = #{id}
     </select>
     <select id="findList" parameterType="java.lang.String" resultMap="userResult">
         select