我的J2E应用程序存在很大问题。它是一个实现RESTFUL API的应用程序。我希望通过身份验证插入一些安全性来区分普通用户和管理员。在认证实现之前,@ GET @POST等..方法是否有效。这是我的提供商的代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.m2acsi.util;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import javax.annotation.security.DenyAll;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.m2acsi.boundary.AdminRessource;
import org.m2acsi.entity.Admin;
/**
*
* @author Michel
*/
@Provider
public class AutentificatorFilter implements ContainerRequestFilter{
private AdminRessource ressource;
@Context
private ResourceInfo resourceInfo;
private static final String AUTORISATION="authorization", SCHEMA="Basic";
private static final Response ACCESS_DENIED= Response.status(Response.Status.UNAUTHORIZED).build();
private static final Response ACCESS_FORBIDEN= Response.status(Response.Status.FORBIDDEN).build();
@Override
public void filter(ContainerRequestContext rc){
Method method = resourceInfo.getResourceMethod();
if (!method.isAnnotationPresent(PermitAll.class)){ //On teste si la méthode renvoyé (GET, POST...) est permise pour tous
if(method.isAnnotationPresent(DenyAll.class)){ //On teste si la méthode est interdite pour tous le monde, dans ce cas on refuse l'accès
rc.abortWith(ACCESS_FORBIDEN);
return;
}
}
final MultivaluedMap<String,String> headers = rc.getHeaders();
final List<String> autorisation = headers.get(AUTORISATION);
if (autorisation == null || autorisation.isEmpty()){
throw new NotAuthorizedException("BASIC realm=\"passport\"");
}
final String motdepasseencode = autorisation.get(0).replaceFirst(SCHEMA+" ","");
String userplusmdp = new String(Base64.getDecoder().decode(motdepasseencode.getBytes()));
final StringTokenizer tokenizer = new StringTokenizer(userplusmdp,":");
final String user = tokenizer.nextToken();
final String mdp = tokenizer.nextToken();
if (method.isAnnotationPresent(RolesAllowed.class)){
RolesAllowed roles = method.getAnnotation(RolesAllowed.class);
Set<String> rolesSet = new HashSet<>(Arrays.asList(roles.value()));
if(!isUserAllowed(user,mdp,rolesSet)){
rc.abortWith(ACCESS_DENIED);
}
}
}
//On test si l'utilisateur qui souhaite faire une demande particulière est bien admin
private boolean isUserAllowed(final String user, final String mdp, final Set<String> roles){
boolean isAllowed = false;
List<Admin> admin = this.ressource.getAll();
String userRole = "ADMIN";
for (Admin a : admin) {
if(user.equals(a.getLogin()) && mdp.equals(a.getMdp())){
if(roles.contains(userRole)){
isAllowed = true;
break;
}
}
}
return isAllowed;
}
}
我的不同实体和资源的代码:
Demande:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.m2acsi.entity;
import java.io.Serializable;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.security.DeclareRoles;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.Pattern;
import org.m2acsi.util.TokenGenerator;
/**
*
* @author Divi
*/
@Entity
@ManagedBean
@ViewScoped
@NamedQuery(name = "Demande.findAll", query = "SELECT d FROM Demande d")
@Table(name = "DEMANDE")
@DeclareRoles("ADMIN")
public class Demande implements Serializable{
@Id
@GeneratedValue
@Column
private long demande_id;
@Column
@Pattern(regexp ="^([a-z]+(( |')[a-z]+)*)+([-]([a-z]+(( |')[a-z]+)*)+)*$",
message ="Merci de saisir un nom valide")
private String nom;
@Column
@Pattern(regexp ="^([a-z]+(( |')[a-z]+)*)+([-]([a-z]+(( |')[a-z]+)*)+)*$",
message ="Merci de saisir un prénom valide")
private String prenom;
@Column
private String sexe;
@Column
@Pattern(regexp ="([a-zA-Z0-9 [-] ]*)",
message ="Merci de saisir un nom valide")
private String adresse;
@Column
private String num_pass;
@Column
private String pays;
@Column
@Pattern(regexp="^(0?[0-9]|[12][0-9]|3[01])/(0?[0-9]|1[012])/((?:19|20)[0-9]{2})$",
message ="Merci de saisir une date de naissance valide")
private String datenaiss;
@Column
private String delivrance;
@Column
private Date expiration;
@Column
private String statut;
@Column
private String token;
@OneToMany (cascade=CascadeType.ALL, mappedBy="demande")
private List<Action> actions = new ArrayList<>();
public Demande() {
}
public Demande(String nom, String prenom, String sexe,
String adresse, String pays, String datenaiss) throws ParseException {
this.nom = nom;
this.prenom = prenom;
this.sexe = sexe;
this.adresse = adresse;
this.pays = pays;
this.datenaiss = datenaiss;
this.statut = "Début";
this.delivrance = null;
this.expiration = null;
this.token = TokenGenerator.generateRandom();
}
public long getId() {
return demande_id;
}
public void setId(long id) {
this.demande_id = id;
}
public String getStatut() {
return statut;
}
public void setStatut(String statut) {
this.statut = statut;
}
public List<Action> getActions() {
return actions;
}
public void setActions(List<Action> actions) {
this.actions = actions;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getPrenom() {
return prenom;
}
public void setPrenom(String prenom) {
this.prenom = prenom;
}
public String getSexe() {
return sexe;
}
public void setSexe(String sexe) {
this.sexe = sexe;
}
public String getAdresse() {
return adresse;
}
public void setAdresse(String adresse) {
this.adresse = adresse;
}
public String getPays() {
return pays;
}
public void setPays(String pays) {
this.pays = pays;
}
public String getDatenaiss() {
return datenaiss;
}
public void setDatenaiss(String datenaiss) {
this.datenaiss = datenaiss;
}
public String getDelivrance() {
return delivrance;
}
public void setDelivrance(String delivrance) {
this.delivrance = delivrance;
}
public Date getExpiration() {
return expiration;
}
public void setExpiration(Date expiration) {
this.expiration = expiration;
}
public void addAction(Action a) {
this.actions.add(a);
}
}
DemandeRessource:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.m2acsi.boundary;
import java.util.List;
import javax.annotation.security.DeclareRoles;
import javax.ejb.Stateless;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceContext;
import org.m2acsi.entity.Action;
import org.m2acsi.entity.Demande;
/**
*
* @author Divi
*/
@DeclareRoles("ADMIN")
@Stateless
public class DemandeRessource {
@PersistenceContext
private EntityManager em;
@Inject
private Event<Demande> listener_d;
@Inject
private Event<Action> listener_a;
//GET ID
public Demande findById(long id) {
return this.em.find(Demande.class, id);
}
//GET ALL
public List<Demande> getAll() {
return this.em.createNamedQuery("Demande.findAll", Demande.class).getResultList();
}
//GET STATUS
public List<Demande> findByStatus(String statut) {
return this.em.createQuery(
"SELECT d FROM Demande d WHERE d.statut = ?1")
.setParameter(1, statut)
.getResultList();
}
//GET ALL ACTIONS
public List<Action> getAllAction(Demande d) {
return this.em.createNamedQuery("Actions.findAll", Action.class)
.setParameter("demande_id", d.getId())
.getResultList();
}
//DELETE
public void delete(long id) {
try {
Demande d = this.em.getReference(Demande.class, id);
this.em.remove(d);
} catch (EntityNotFoundException e) {}
}
//POST Demande
public Demande saveDemande(Demande d) {
Demande dem = this.em.merge(d);
listener_d.fire(dem);
return dem;
}
//POST Action
public Action saveAction(Action a) {
Action act = this.em.merge(a);
listener_a.fire(act);
return act;
}
}
DemandeRepresentation:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.m2acsi.boundary;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.m2acsi.entity.Action;
import org.m2acsi.entity.Demande;
import org.m2acsi.entity.TypeAction;
/**
*
* @author michel
*/
@Stateless
@Path("demandes")
@DeclareRoles("ADMIN")
public class DemandeRepresentation {
@Inject
private DemandeRessource ressource;
@GET // GET id
@Path("{id}")
@Produces({MediaType.APPLICATION_JSON})
public Response findById(@PathParam("id") long id) {
Demande d = this.ressource.findById(id);
if (d != null) {
return Response.ok(d).build();
} else {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
@GET
@Produces({MediaType.APPLICATION_JSON})
@PermitAll
@RolesAllowed("ADMIN")
public List<Demande> findByStatus(@QueryParam("statut") String statut) {
if (statut == null) {
return this.ressource.getAll(); //Si pas de ?statut on getAll
} else {
return this.ressource.findByStatus(statut); //Si statut on findByStatut
}
}
@GET
@Produces({MediaType.APPLICATION_JSON}) //Get demandes/{id}/actions
@Path("{id}/actions")
public List<Action> findAllActionsByDemande(@PathParam("id") long id) {
Demande d = this.ressource.findById(id);
return d.getActions();
}
@GET
@Produces({MediaType.APPLICATION_JSON}) //GET demandes/{id}/actions/{aid}
@Path("{id}/actions/{aid}")
public Action findActionById(@PathParam("id") long id, @PathParam("aid") int aid) {
Demande d = this.ressource.findById(id);
Action rep = null;
for (Action a : d.getActions()) {
if (a.getAid() == aid) {
rep = a;
break;
}
}
return rep;
}
@POST //POST demandes
public Response saveDemande(Demande d, @Context UriInfo uriInfo) {
d.setStatut("Début");
Action a = new Action(TypeAction.ATTENTE_ATTRIBUTION, "Michel", "en cours");
d.addAction(a);
Demande saved = this.ressource.saveDemande(d);
long idd = saved.getId();
URI uri = uriInfo.getAbsolutePathBuilder().path("/" + idd).build();
return Response.created(uri).build();
}
@POST //POST demandes/{id}/actions
@Path("{id}/actions")
public Response saveAction(@PathParam("id") long id, Action a, @Context UriInfo uriInfo) {
Demande d = this.ressource.findById(id);
d.addAction(a);
Action saved = a;
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy H:mm:ss");
saved.setDate(formatter.format(new Date()));
saved = this.ressource.saveAction(a);
long idd = saved.getAid();
URI uri = uriInfo.getAbsolutePathBuilder().path("/" + id +"actions/"+ idd).build();
return Response.created(uri).build();
}
@PUT
@Path("{id}")
public Demande updateDemande(@PathParam("id") long id, Demande d) {
d.setId(id);
return this.ressource.saveDemande(d);
}
@PUT
@Path("{id}/actions/{aid}")
public Action updateAction(@PathParam("id") long id, @PathParam("aid") int aid, Action a) {
a.setAid(aid);
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy H:mm:ss");
a.setDate(formatter.format(new Date()));
return this.ressource.saveAction(a);
}
@DELETE
@Path("{id}")
public void delete(@PathParam("id") long id) {
this.ressource.delete(id);
}
}
管理员:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.m2acsi.entity;
import java.io.Serializable;
import javax.annotation.security.DeclareRoles;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
/**
*
* @author michel
*/
@Entity
@Table(name = "ADMIN")
@NamedQuery(name="Admin.findAll", query="SELECT a FROM Admin a")
@DeclareRoles("ADMIN")
public class Admin implements Serializable{
@Id
@Column(name = "LOGIN")
private String login;
@Column(name = "MDP")
private String mdp; //A crypter
public Admin(){}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getMdp() {
return mdp;
}
public void setMdp(String mdp) {
this.mdp = mdp;
}
}
AdminRessource:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.m2acsi.boundary;
import java.util.List;
import javax.annotation.security.DeclareRoles;
import javax.ejb.Stateless;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceContext;
import org.m2acsi.entity.Action;
import org.m2acsi.entity.Admin;
/**
*
* @author Divi
*/
@DeclareRoles("ADMIN")
@Stateless
public class AdminRessource {
@PersistenceContext
private EntityManager em;
@Inject
private Event<Admin> listener;
//GET ALL
public List<Admin> getAll() {
List<Admin> admins = this.em.createNamedQuery("Admin.findAll", Admin.class).getResultList();
System.out.println(admins.get(0).getLogin());
return admins;
}
}
编辑:例外的StackTrace:
Avertissement: StandardWrapperValve[org.m2acsi.passport.JAXRSConfiguration]: Servlet.service() for servlet org.m2acsi.passport.JAXRSConfiguration threw exception
java.lang.NullPointerException
at org.m2acsi.util.AutentificatorFilter.isUserAllowed(AutentificatorFilter.java:78)
at org.m2acsi.util.AutentificatorFilter.filter(AutentificatorFilter.java:69)
at org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:132)
at org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:68)
at org.glassfish.jersey.process.internal.Stages.process(Stages.java:197)
at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:309)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:298)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:471)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:425)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:383)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:336)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:223)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:416)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:283)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
at java.lang.Thread.run(Thread.java:745)
Infos: keepstate options resolved to true, saving appId 95366951280836608 for application passport.
Infos: /file:/C:/Users/michel/Documents/NetBeansProjects/passport/passport/target/passport/WEB-INF/classes/_org.m2acsi_passport_war_1.0PU logout successful
Grave: One cannot have more than one of @RolesAllowed, @PermitAll, @DenyAll in the same AnnotatedElement.
symbol: METHOD location: public java.util.List org.m2acsi.boundary.DemandeRepresentation.findByStatus(java.lang.String)
Grave: One cannot have more than one of @RolesAllowed, @PermitAll, @DenyAll in the same AnnotatedElement.
symbol: METHOD location: public java.util.List org.m2acsi.boundary.DemandeRepresentation.findByStatus(java.lang.String)
如果您有任何想法来解决它,请享受! 谢谢。
答案 0 :(得分:0)
我找到了解决这个问题的方法。要询问我的数据库以了解哪些人可以访问我的资源,有必要在我的类AutentificatorFilter中的AdminRessource属性之前添加@EJB注释。