WEB应用前后端分离实践 关键词:rest架构+跨域访问+JWT校验 -CSDN论坛 - 002

  (四)、过滤器处理
在过滤器当中需要添加一些不需要进行token校验的请求路径,可以直接访问。 在这里没有角色权限的校验,有需要的可以自行设计。

Java code?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

package ichano.developer.sys.filter;`/**`

import ichano.developer.biz.service.ZyLoginService;

import ichano.developer.dto.ZyUserDto;

import ichano.developer.util.KeyUtil;

import ichano.developer.util.TokenUtil;

import java.io.IOException;

import java.security.Key;

import javax.annotation.Priority;

import javax.inject.Inject;

import javax.servlet.ServletContext;

import javax.ws.rs.Priorities;

import javax.ws.rs.WebApplicationException;

import javax.ws.rs.container.ContainerRequestContext;

import javax.ws.rs.container.ContainerRequestFilter;

import javax.ws.rs.container.PreMatching;

import javax.ws.rs.core.Context;

import javax.ws.rs.core.MultivaluedMap;

import javax.ws.rs.core.Response;

import javax.ws.rs.core.UriInfo;

import javax.ws.rs.ext.Provider;

import org.apache.log4j.LogManager;

import org.apache.log4j.Logger;

import org.glassfish.jersey.server.ContainerRequest;

import org.springframework.beans.factory.annotation.Autowired;

/** 

* @ClassName: JWTSecurityFilter 

* @Description: TODO(权限验证过滤器) 

* @author lizhijun

* @date 2016年8月11日 下午1:18:52 

*  

*/

@Provider

@Priority`(Priorities.AUTHENTICATION)`//优先级最高

//实现该拦截器借口

//@Provider可以自动注册

@PreMatching         //这个必须添加,否则无法拦截请求

public class JWTSecurityFilter `implements ContainerRequestFilter{`

final static Logger logger = LogManager.getLogger(JWTSecurityFilter.`class`.getName());

@Autowired

ZyLoginService zyLoginService;

@Context

ServletContext context;

@Inject

javax.inject.Provider<UriInfo> uriInfo;

public static String extractJwtTokenFromAuthorizationHeader(String auth) {

//Replacing "Bearer Token" to "Token" directly

return auth.replaceFirst(`"B|bA|aE|e """).replace(" """`);

}

//重写验证过滤器

@Override

public void filter(ContainerRequestContext containerRequestContext) `throws IOException {`

//获取本地的私钥

Key key= KeyUtil.getKey(context);

//得到访问的方法 例如GET,POST

String method = containerRequestContext.getMethod().toLowerCase();

//预校验请求处理

if`(method.equals("options")){`

containerRequestContext.setSecurityContext(`new SecurityContextAuthorizer(uriInfo,new` `AuthorPricinple("pass"), new String[]{"pass"}));`

return`;`

}

//得到访问路径

String path = ((ContainerRequest) containerRequestContext).getPath(`true`).toLowerCase();

System.err.println(`"authorizationHeader path is :"`+path);

//不需要验证,post验证过滤,注册过滤。

if (`"post".equals(method) && "developer/loginuser"`.equals(path)

|| `"developer/registeruser"`.equals(path)

|| `"developer/sendverifcode"`.equals(path)

|| `"developer/updatepwd"`.equals(path) 

||`"license/uploadfilecheck"`.equals(path)

||`"product/uploadproductimg"`.equals(path)) {

containerRequestContext.setSecurityContext(`new SecurityContextAuthorizer(uriInfo,new` `AuthorPricinple("pass"), new String[]{"pass"}));`

return`;`

}

//获取头信息中的token

MultivaluedMap<String, String> testToken = ((ContainerRequest) containerRequestContext).getHeaders();

String authorizationHeader = ((ContainerRequest) containerRequestContext).getHeaderString(`"auth_token"`);

//如果token为空抛出

if (authorizationHeader == `null`) {

throw new WebApplicationException(Response.Status.UNAUTHORIZED);`//抛出未认证的错误`

}

//把Bear Token换成Token

String strToken=extractJwtTokenFromAuthorizationHeader(authorizationHeader);

if (TokenUtil.isValid(strToken,key)){

String name=TokenUtil.getName(strToken,key);`//反解出Name`

//            String[] roles=TokenUtil.getRoles(strToken,key);//反解出角色

if`(name !=null){`

ZyUserDto user=zyLoginService.findUserByName(name);

if`(user!=null){`

containerRequestContext.setSecurityContext(`new SecurityContextAuthorizer(uriInfo,new` `AuthorPricinple(name), new String[]{"user"}));`

return`;`

}

else`{`

logger.info(`"User not found " + name);`

}

}

else {

logger.info(`"name, roles or version missing from token"`);

}

}

else {

logger.info(`"token is invalid"`);

}

throw new WebApplicationException(Response.Status.UNAUTHORIZED);

}

}

   (五)、前端请求代码
采用ajax post请求方式。
 // 发送登陆请求
  

JavaScript code?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

$.ajax({

url: `"http://192.168.0.55:8080/developer/developer/loginUser"`,

type: `"POST"`,

dataType: `"json"`,

contentType: `"application/json",      <span style="color: #FF0000;">    //注意:如果有post data参数的时候,必须加这段,否则请求获取不到参数</span>      `

data: {

user_name: userName,

password: userPwd,

type: type

},

success: `function`(data) {

console.log(data);

if (data.code == 1000) {

$.cookie(`'token'`, data.data.token);

console.log(1);

parent.location.reload();

`else if (data.code == 2006) {`

layer.msg(`"用户名密码错误"`);

`else {`

layer.msg(`"登陆异常"`);

}

}

});

//访问接口请求

JavaScript code?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

$.ajax({

url: `"http://192.168.0.181:9102/developer/developer/checkLogin"`,

type: `'POST'`,

dataType: `'json'`,

beforeSend: `function(request) {                       //添加请求响应头中的自定义token`

request.setRequestHeader(`"auth_token"`, token);

},

success: `function`(data) {

if (data.code == 1000) {

var html = [];

html.push(Mustache.render(userNameTemp, data.data));

$userNameCon.html(html.join(`''`));

`else {`

window.location.href = `"index.html"`

}

}

})

二、CORS跨域访问     
        使用cors进行跨域配置其实很简单,只需要引用jar包,然后添加过滤器即可。但是有些细节还是要注意。
       (一)、jar包引用
         <dependency>
            <groupId>com.thetransactioncompany</groupId>
            <artifactId>cors-filter</artifactId>
            <version>2.5</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.thetransactioncompany/java-property-utils -->
        <dependency>
            <groupId>com.thetransactioncompany</groupId>
            <artifactId>java-property-utils</artifactId>
            <version>1.9.1</version>
        </dependency>
(二)、过滤器实现
         web.xml配置:

Java code?

1

2

3

4

5

6

7

8

<filter>

<filter-name>cros</filter-name>

<filter-`class>ichano.developer.sys.filter.CorsFilter</filter-class`>

</filter>

<filter-mapping>

<filter-name>cros</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

过滤器中可以配置允许访问的请求方,允许访问的请求方式以及允许通过的请求头信息

Java code?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

package ichano.developer.sys.filter;`/**`

import java.io.IOException;

import javax.servlet.FilterChain;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.filter.OncePerRequestFilter;

/** 

* @ClassName: CorsFilter 

* @Description: TODO(设置其他IP地址的机器可以直接访问本项目Url--工具filter) 

* @author lizhijun

* @date 2016年8月15日 下午2:25:25 

*  

*/

public class CorsFilter `extends OncePerRequestFilter {`

@Override

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) `throws ServletException, IOException {`

response.addHeader(`"Access-Control-Allow-Origin""");      //为安全起见,可配置允许访问的请求方地址。这里配置成号,是允许所有访问。`

response.addHeader(`"Access-Control-Allow-Methods""GET, POST, PUT, DELETE");        //为安全起见,也可配置成只允许POST请求`

response.addHeader(`"Access-Control-Allow-Headers""Content-Type,auth_token");      //这里要注意,auth_token是我自定义的请求头当中带的token,在这里必须添加,否则你永远获取不到。`

response.addHeader(`"Access-Control-Max-Age""1800");//30 min`

filterChain.doFilter(request, response);

}

}

        这里处理了三个坑,
**一是在本地调试的时候可以跨域访问,但是部署到服务器之后,访问失败。解决方法:请求地址后面加上端口号就可以访问。  这个问题就需要在nignx里面进行端口配置。
二是CROS这种传输方式传输的数据到后端接收已不是JSON格式,而是类似于XXX=123&FFFF=384这样的格式,需要对所有请求的入参进行一下转换成json格式。
三是请求头中的自定义字段auth_token在服务器上接收不到,这里需要对ngnix进行配置,允许自定义属性的header配置。
[b]**


Original url: Access
Created at: 2020-09-02 17:59:02
Category: default
Tags: none

请先后发表评论
  • 最新评论
  • 总共0条评论