我的web.xml文件对REST api有限制,使用url /rs/private/*/
,如下所示:
<security-constraint>
<web-resource-collection>
<web-resource-name>PRIVATE REST API</web-resource-name>
<url-pattern>/rs/private/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>HEAD</http-method>
<http-method>PUT</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<description>Have to be a USER</description>
<role-name>USERS</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>userauth</realm-name>
</login-config>
<security-role>
<description/>
<role-name>USERS</role-name>
</security-role>
从角度来看,我在授权http标头中发送了承载+令牌:
$httpProvider.interceptors.push(['$q', '$location', 'store', function ($q, $location, store) {
return {
'request': function (config) {
config.headers = config.headers || {};
if (store.get('jwt')) {
config.headers.Authorization = 'Bearer ' + store.get('jwt');
}
return config;
},
'responseError': function (response) {
if (response.status === 401 || response.status === 403) {
$location.path('/Login');
}
return $q.reject(response);
}
};
}]);
firefox中的请求标头:
Accept
application/json, text/plain, */*
Accept-Encoding
gzip, deflate
Accept-Language
en-US,en;q=0.5
Authorization
Bearer eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wvcnRoLmNvbSIsInN1YiI6IlJUSCIsImV4cCI6MTQ1Mjk3Nzc4NiwiZW1haWwiOiJraXJpdGkuazk5OUBnbWFpbC5jb20ifQ
.SwyVMdweHgH3eQ-IYDUsjavAbUYPWQTSvdrIKMVQEzDTIsgvpWsoR13SJsV6kHrC_2uelBG0aSgExj794xe5yrK7VQ8J4yPRrXT
1EPf4LyABuHltHJNVtR_PRpPxcLZnP4GAQm-ozBVyHarsCpI9FINwhepY4_Lt51lU_EtDjI4
Host
localhost:7070
Referer
http://localhost:7070/RTH_Sample13/
User-Agent
Mozilla/5.0 (Windows NT 6.3; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0
问题是当我在java中打印请求标头时,我找不到从angular发送的授权标头:
@Path("/public/loginResource")
public class LoginService {
@Context
private UriInfo context;
public LoginService() {
}
@POST
@Path("/login")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response authenticateUser(@Context HttpServletRequest request, Credentials credentials) {
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = (String) headerNames.nextElement();
System.out.println(headerName);
//PRINTS: host user-agent accept accept-language accept-encoding content-type referer content-length connection
}
String email = credentials.getEmail();
String password = credentials.getPassword();
String token = "";
try {
LoginDAO loginDao = new LoginDAO();
if (loginDao.authenticate(email, password)) {
TokenProvider jwtProvider = new TokenProvider();
token = jwtProvider.getToken(email);
Map<String, String> response = new HashMap<String, String>();
response.put("token", token);
return Response.ok(response).build();
} else {
return Response.status(Response.Status.UNAUTHORIZED).type("text/plain").entity("Invalid Username or Password!").build();
}
} catch (Exception e) {
e.printStackTrace();
return Response.status(Response.Status.NOT_FOUND).type("text/plain").entity("Error in Login Service web service class").build();
}
}
}
我想要实现的是我想拦截每个请求,并使用某种过滤器使用授权标头和令牌识别用户。
这里有两个问题:
Authorization
标头答案 0 :(得分:0)
评论太长了。
至于你的第一个问题,我不是angularjs
而是纯js
,看着我的代码,我会写'Basic ' + store.get('jwt')
而不是'Bearer ' + store.get('jwt')
。
关于你的第二个问题,正如在其他评论中一样,关于球衣认证过滤器的问题很多。这很简单,你可以看看,例如here
但是,如果您想手动执行此操作,则必须在每项服务中执行此操作。 (我真的不明白为什么添加过滤器会成为一个问题,但无论如何)。
这将是这样的(实际上,你将在过滤器中做同样的事情):
@GET
@Produces(MediaType.APPLICATION_JSON)
public <your_output_class> yourService(@Context final ContainerRequestContext requestContext) {
String authentication = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
if (! authentication.startsWith("Basic ")) {
throw new <your_exception>("Not authenticated");
}
authentication = authentication.substring("Basic ".length());
String[] values = Base64.decodeAsString(authentication).split(":");
if (values.length < 2) {
throw new <your_exception>("Invalid syntax for username and password");
}
...
然后你会检查ddbb或用来存储用户和密码的任何内容。
当然,您需要将其放入实用方法或类似的东西中。
最后,如果您使用的是CORS,则必须小心,具体取决于您的客户端,您可能会有一个带有空标头的preflight
请求。不知道angularjs
是否做到了。请告诉我。
希望它有所帮助!