Security trong Restful Webservice sử dụng Jersey 2 để sinh ra JWT
Đăng lúc: 07:24 PM - 29/11/2023 bởi Charles Chung - 1023Trong bài viết này tôi sẽ hướng dẫn các bạn cách bảo mật Restful Webservice, chúng ta sẽ sử dụng thư viện Jersey 2 để sinh ra JWT Bearer, cơ sở dữ liệu sử dụng Oracle, truy xuất dữ liệu sử dụng Hibernate
Giới thiệu Token-based Authentication
JSON Web Token (JWT) là 1 tiêu chuẩn mở (RFC 7519), định nghĩa cách thức truyền tin an toàn giữa các ứng dụng bằng một đối tượng JSON. Dữ liệu truyền đi sẽ được mã hóa và chứng thực, có thể được giải mã để lấy lại thông tin và đánh dấu tin cậy nhờ vào “chữ ký” của nó. Phần chữ ký của JWT sẽ được mã hóa lại bằng HMAC hoặc RSA. Chi tiết các bạn xem lại bài viết “Giới thiệu Json Web Token (JWT)“.
Token-based Authentication là cơ chế xác thực người dùng dựa trên việc tạo ra token – một chuỗi ký tự (thường được mã hóa) mang thông tin xác định người dùng được server tạo ra và lưu ở client. Server sau đó có thể không lưu lại token này.
Token-based Authentication trong Jersey 2.x
Mô tả yêu cầu:
- Tạo Restful Webservice "StudentService" cung cấp các method GET, POST, PUT, DELETE để thao tác dữ liệu với bảng Student (xem cấu trúc trong hình dưới). Áp dụng cơ chế bảo mật cho các method trong Rest Webservice bằng cách sử dụng Token để xác thực người dùng khi truy cập vào StudentService, tài khoản người dùng sẽ được gán ROLE rõ ràng (role gồm 2 loại ADMIN và STUDENT), apply ROLE cho các method để kiểm thử.
- Cơ sở dữ liệu sử dụng Oracle.
- Mật khẩu sử dụng MD5 mã hóa.
- Truy xuất dữ liệu sử dụng Hibernate.
Giải pháp
Bước 1: Tạo cơ sở dữ liệu có tên "bkap" trong oracle với các bảng mô tả như sau:
Dữ liệu mẫu xem trong file bkap_jwt.sql trong source đính kèm
Bước 2: Tạo Dynamic Web Project (xem chi tiết bài Phát triển ứng dụng RESTful Web Service trong Java với thư viện Jersey )
- Khởi động Eclispe IDE -> vào menu File -> New -> Dynamic Web Project -> Nhập tên "RestfulWebServiceJWT"
- Tiêp tục kích vào Next -> Next -> Chọn Generate web.xml deyployment desciptor
Bước 3: Convert sang Maven Project
- Kích chuột phải vào Project vừa tạo -> Configure -> Convert to Maven Project -> Finish
Bước 4: Khai báo các Maven Dependencies cần thiết
- Mở file pom.xml và cấu hình các Maven Dependencies gồm: jersey server 2, gson, hibernate, oracle, jaxb api, jsonwebtoken,..
<dependencies>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.26.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc10 -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc10</artifactId>
<version>19.20.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.41</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-server -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.41</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.41</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-json-jackson -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.41</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.10.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
</dependencies>
Bước 5: Cấu hình ứng dụng Jersey Servlet
- Mở tệp web.xml và cấu hình vào bên trong thẻ <web-app> như sau:
<servlet>
<servlet-name>jersey2Serlvet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>hanam88.api</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>hanam88.api</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.filter.LoggingFilter;
org.glassfish.jersey.jackson.JacksonFeature;
hanam88.filter.AuthFilter;
org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey2Serlvet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
Bước 6: Tạo các package và các class theo cấu trúc sau
- Tệp cấu hình hibernate.cfg.xml (cấu hình kết nối cơ sở dữ liệu oracle và hibernate)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:bkap</property>
<property name="hibernate.connection.password">1234$</property>
<property name="hibernate.connection.username">system</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle12cDialect</property>
<mapping class="hanam88.model.Student" />
<mapping class="hanam88.model.Account" />
<mapping class="hanam88.model.AccountRole" />
<mapping class="hanam88.model.Role" />
</session-factory>
</hibernate-configuration>
- Tạo lớp hanam88.dao\HibernateUtil.java (đọc thông tin cấu hình trong tệp hibernate.cfg.xml và tạo sessionfactory)
public class HibernateUtil {
public static SessionFactory getSessionFactory() {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
return sf;
}
}
- Tạo lớp hanam88.model\Account.java
@Entity
@Table(name="accounts")
public class Account {
@Id
@Column(name = "accountid")
private String accountid;
@Column(name = "username")
private String userName;
@Column(name = "password")
private String passWord;
@Column(name = "fullname")
private String fullName;
@Column(name = "gender")
private int gender;
@Column(name = "birthday")
@Temporal(value = TemporalType.DATE)
private Date birthday;
@Column(name = "email")
private String email;
@Column(name = "phone")
private String phone;
@Column(name = "avatar")
private String avatar;
@Column(name = "note")
private String note;
@Column(name = "active")
private int active;
@OneToMany(mappedBy = "account", fetch = FetchType.EAGER)
private Set<AccountRole> accountroles;
public Account() {
// TODO Auto-generated constructor stub
}
public String getAccountid() {
return accountid;
}
public void setAccountid(String accountid) {
this.accountid = accountid;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
public Set<AccountRole> getAccountroles() {
return accountroles;
}
public void setAccountroles(Set<AccountRole> accountroles) {
this.accountroles = accountroles;
}
}
- Tạo lớp hanam88.model\Role.java
@Entity
@Table(name="roles")
public class Role {
@Id
@Column(name = "roleid")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "rolename")
private String rolename;
@OneToMany(mappedBy = "role")
private Set<AccountRole> accountroles;
public Role() {
// TODO Auto-generated constructor stub
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRolename() {
return rolename;
}
public void setRolename(String rolename) {
this.rolename = rolename;
}
public Set<AccountRole> getAccountroles() {
return accountroles;
}
public void setAccountroles(Set<AccountRole> accountroles) {
this.accountroles = accountroles;
}
}
- Tạo lớp hanam88.model\AccountRole.java
@Entity
@Table(name="accounts_roles")
public class AccountRole {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "accountId")
private Account account;
@ManyToOne
@JoinColumn(name = "roleId")
private Role role;
public AccountRole() {
// TODO Auto-generated constructor stub
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
- Tạo lớp hanam88.model\AccountDetail.java
//Lớp customize Principal để lưu thêm thông tin người dùng
public class AccountDetail implements Principal{
private String username;
private String password;
private String fullName;
private int gender;
private String email;
private String phone;
private String avatar;
private List<String> roles = new ArrayList<>();
public AccountDetail() {
}
public AccountDetail(Account user) {
if (user != null) {
this.username = user.getUserName();
this.password = user.getPassWord();
this.avatar = user.getAvatar();
this.email = user.getEmail();
this.fullName = user.getFullName();
System.out.println(this.fullName);
this.gender = user.getGender();
this.phone = user.getPhone();
var accroles = user.getAccountroles();
for (AccountRole accountRole : accroles) {
this.roles.add(accountRole.getRole().getRolename());
}
}
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<String> getRoles() {
return roles;
}
public void setRoles(List<String> roles) {
this.roles = roles;
}
@Override
public String getName() {
return username;
}
}
- Tạo lớp hanam88.model\Student.java
@Entity
@Table(name = "students")
public class Student {
@Id
private String studentId;
private String fullName;
private int gender;
@Temporal(TemporalType.DATE)
private Date birthDay;
private String email;
private String phone;
private String address;
private int active;
public Student() {
// TODO Auto-generated constructor stub
}
public String getStudentId() {
return studentId;
}
public Student(String studentId, String fullName, int gender, Date birthDay, String email, String phone,
String address, int active) {
super();
this.studentId = studentId;
this.fullName = fullName;
this.gender = gender;
this.birthDay = birthDay;
this.email = email;
this.phone = phone;
this.address = address;
this.active = active;
}
public void setStudentId(String studentId) {
this.studentId = studentId;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public Date getBirthDay() {
return birthDay;
}
public void setBirthDay(Date birthDay) {
this.birthDay = birthDay;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
}
- Tạo lớp hanam88.model\BasicSecurityContext.java
public class BasicSecurityContext implements SecurityContext {
private AccountDetail user;
private boolean secure;
public BasicSecurityContext(AccountDetail user, boolean secure) {
this.user = user;
this.secure = secure;
}
@Override
public AccountDetail getUserPrincipal() {
return user;
}
@Override
public boolean isUserInRole(String role) {
return user.getRoles().contains(role);
}
@Override
public boolean isSecure() {
return secure;
}
@Override
public String getAuthenticationScheme() {
return SecurityContext.BASIC_AUTH;
}
}
- Tạo lớp hanam88.dao\AccountDAO.java
public class AccountDAO {
SessionFactory sf = HibernateUtil.getSessionFactory();
//lấy thông tin người dùng theo username
public AccountDetail getUser(String username) {
Session session=sf.openSession();
Account account = (Account) session.createQuery("from Account where username = :username")
.setParameter("username", username).uniqueResult();
session.close();
if(account!=null)
return new AccountDetail(account);
else
return null;
}
}
- Tạo lớp hanam88.dao\StudentDAO.java
public class StudentDAO {
SessionFactory sf = HibernateUtil.getSessionFactory();
public List<Student> getAll() {
Session session = sf.openSession();
List<Student> data = new ArrayList<>();
Query query = session.createQuery("from Student");
data = query.getResultList();
session.close();
return data;
}
public Student getById(String studentId) {
Session session = sf.openSession();
Student student = session.get(Student.class, studentId);
session.close();
return student;
}
public void insert(Student st) {
Session session = sf.openSession();
session.beginTransaction();
session.save(st);
session.getTransaction().commit();
session.close();
}
public void update(Student st) {
Session session = sf.openSession();
session.beginTransaction();
session.update(st);
session.getTransaction().commit();
session.close();
}
public Student delete(String studentId) {
Session session = sf.openSession();
session.beginTransaction();
Student student = session.get(Student.class, studentId);
if (student != null) {
session.remove(student);
session.getTransaction().commit();
}
session.close();
return student;
}
}
- Tạo lớp hanam88.helper\MD5Encoder.java
public class MD5Encoder {
public static String GenerateMD5(String data){
try {
// gọi phương thức tạo đối tượng mã hóa MD5
MessageDigest md = MessageDigest.getInstance("MD5");
//chuyển chuỗi mã hóa về dạng byte
byte[] messageDigest = md.digest(data.getBytes());
//chuyển mảng byte thành ký số
BigInteger no = new BigInteger(1, messageDigest);
// convert thành chuỗi hexa 16
String hashtext = no.toString(16);
while (hashtext.length() < 32) {
hashtext = "0" + hashtext;
}
return hashtext;
} catch (NoSuchAlgorithmException ex) {
System.out.println("Sai tên giải thuật");
}
return null;
}
}
- Tạo lớp hanam88.helper\JwTokenHelper.java
public class JwTokenHelper {
// The privateKey is only valid for the given minutes
private static final long EXPIRATION_LIMIT_IN_MINUTES = 30;
// The JWT signature algorithm we will be using to sign the token
private static final SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256;
// Keys used with HS256 MUST have a size >= 256 bits
private static final String SECRET_KEY = "hanam88dotcom-jwt-restful-webservice-with-oracle-example";
private static final String ISSUER = "https://hanam88.com";
private JwTokenHelper() {
super();
}
public static String createJWT(AccountDetail user) {
// Get the current time
long currentTimeInMillis = System.currentTimeMillis();
Date now = new Date(currentTimeInMillis);
// The privateKey is only valid for the next EXPIRATION_LIMIT_IN_MINUTES
long expirationTimeInMilliSeconds = TimeUnit.MINUTES.toMillis(EXPIRATION_LIMIT_IN_MINUTES);
Date expirationDate = new Date(currentTimeInMillis + expirationTimeInMilliSeconds);
// Will sign our JWT with our ApiKey secret
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET_KEY);
Key signingKey = new SecretKeySpec(apiKeySecretBytes, SIGNATURE_ALGORITHM.getJcaName());
// Sets the JWT Claims sub (subject) value
Claims claims = Jwts.claims().setSubject(user.getUsername());
//thêm thông tin người dùng vào claims
claims.put("roles", user.getRoles());
claims.put("fullname", user.getFullName());
claims.put("avatar", user.getAvatar());
// Let's set the JWT Claims
JwtBuilder builder = Jwts.builder() // Configured and then used to create JWT compact serialized strings
.setClaims(claims).setId(UUID.randomUUID().toString()) // Sets the JWT Claims jti (JWT ID) value
.setIssuedAt(now) // Sets the JWT Claims iat (issued at) value
.setIssuer(ISSUER) // Sets the JWT Claims iss (issuer) value
.setExpiration(expirationDate) // Sets the JWT Claims exp (expiration) value
.signWith(signingKey, SIGNATURE_ALGORITHM);
// Builds the JWT and serializes it to a compact, URL-safe string
return builder.compact();
}
/**
* Get User from the given token
*/
public static AccountDetail getUserFromToken(String token) {
//decode jwt token
final Claims claims = decodeJWT(token);
//lấy thông tin người dùng trong claims
AccountDetail user = new AccountDetail();
user.setUsername(claims.getSubject());
user.setFullName(claims.get("fullname").toString());
user.setAvatar(claims.get("avatar").toString());
user.setRoles((List<String>) claims.get("roles"));
return user;
}
/**
* Check if the token was issued by the server and if it's not expired
*/
public static Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
private static Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
private static <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = decodeJWT(token);
return claimsResolver.apply(claims);
}
private static Claims decodeJWT(String jwt) {
// This line will throw an exception if it is not a signed JWS (as expected)
return Jwts.parser() // Configured and then used to parse JWT strings
.setSigningKey(DatatypeConverter.parseBase64Binary(SECRET_KEY)) // Sets the signing key used to verify
// any discovered JWS digital signature
.parseClaimsJws(jwt) // Parses the specified compact serialized JWS string based
.getBody();
}
}
- Tạo lớp hanam88.filter\AuthFilter.java
@Provider
@Priority(Priorities.AUTHENTICATION) // xảy ra trước khi xác thực
public class AuthFilter implements ContainerRequestFilter {
private static final String REALM = "hanam88";
private static final String AUTHENTICATION_SCHEME = "Bearer";
/**
* Extracting the token from the request and validating it
*
* The client should send the token in the standard HTTP Authorization header of
* the request. For example: Authorization: Bearer <token-goes-here>
*
* Finally, set the security context of the current request
*/
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// (1) Get Token Authorization from the header
String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// (2) Validate the Authorization header
if (!isTokenBasedAuthentication(authorizationHeader)) {
return;
}
// (3) Extract the token from the Authorization header
String token = authorizationHeader.substring(AUTHENTICATION_SCHEME.length()).trim();
try {
// (4) Validate the token
if (JwTokenHelper.isTokenExpired(token)) {
abortWithUnauthorized(requestContext);
return;
}
// (5) Getting the User information from token
AccountDetail user = JwTokenHelper.getUserFromToken(token);
// (6) Overriding the security context of the current request
SecurityContext oldContext = requestContext.getSecurityContext();
requestContext.setSecurityContext(new BasicSecurityContext(user, oldContext.isSecure()));
} catch (Exception e) {
abortWithUnauthorized(requestContext);
}
}
private boolean isTokenBasedAuthentication(String authorizationHeader) {
// Check if the Authorization header is valid
// It must not be null and must be prefixed with "Bearer" plus a whitespace
// The authentication scheme comparison must be case-insensitive
return authorizationHeader != null
&& authorizationHeader.toLowerCase().startsWith(AUTHENTICATION_SCHEME.toLowerCase() + " ");
}
private void abortWithUnauthorized(ContainerRequestContext requestContext) {
// Abort the filter chain with a 401 status code response
// The WWW-Authenticate header is sent along with the response
Response respone = Response.status(Response.Status.UNAUTHORIZED) // 401 Unauthorized
.header(HttpHeaders.WWW_AUTHENTICATE, AUTHENTICATION_SCHEME + " realm=\"" + REALM + "\"")
.entity("Bạn không thể truy cập vào tài nguyên này") // the response entity
.build();
requestContext.abortWith(respone);
}
}
- Tạo lớp hanam88.filter\AuthService.java
@Path("/gettoken")
public class AuthService {
/**
* Xác thực người dùng với username/password của họ và phát hành token
*
* @param username
* @param password
* @return JSON Web Token (JWT)
*/
@POST
@Produces(MediaType.TEXT_PLAIN)
@Consumes(MediaType.APPLICATION_JSON)
public Response createToken(String usermodel) {
var gson=new Gson();
var user=gson.fromJson(usermodel, AccountDetail.class);
String username=user.getUsername();
//mã hóa password MD5
String password=MD5Encoder.GenerateMD5(user.getPassword());
// Xác thực người dùng bằng thông tin đăng nhập được cung cấp
AccountDAO accountDAO = new AccountDAO();
//lấy tài khoản theo username
user = accountDAO.getUser(username);
if (user == null || !user.getPassword().equals(password)) {
return Response.status(Response.Status.FORBIDDEN)
.entity("Sai tên hoặc mật khẩu") // tạo thực thể trả về
.build();
}
// Tạo token dựa trên thông tin user
String token = JwTokenHelper.createJWT(user);
// trả về chuối token
return Response.ok(token).build();
}
}
- Tạo lớp hanam88.filter\StudentService.java
@Path("/students")
@PermitAll
public class StudentService {
private StudentDAO dao=new StudentDAO();
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getAll() {
var gson=new GsonBuilder().setDateFormat("dd/MM/yyyy").create();
var students= gson.toJson(dao.getAll());
return Response.ok(students).build();
}
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response get(@PathParam("id") String id) {
return Response.ok(dao.getById(id)).build();
}
@RolesAllowed("ROLE_ADMIN")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response insert(String student, @Context SecurityContext securityContext) {
//Lấy thông tin người dùng trên server
var user=(AccountDetail) securityContext.getUserPrincipal();
System.out.println("Xin chào: " + user.getFullName());
System.out.println("Họ tên: " + user.getUsername());
System.out.println("Ảnh: " + user.getAvatar());
//xử lý convert json
var gson=new GsonBuilder().setDateFormat("dd/MM/yyyy").create();
var st=gson.fromJson(student, Student.class);
dao.insert(st);
return Response.ok("Thêm thành công").build();
}
@RolesAllowed({"ROLE_ADMIN", "ROLE_STUDENT" })
@PUT
@Path("/{id}")
public Response update(@PathParam("id") String id, String student) {
//xử lý convert json
var gson=new GsonBuilder().setDateFormat("dd/MM/yyyy").create();
var st=gson.fromJson(student, Student.class);
if(!st.getStudentId().equals(id))
return Response.ok("Mã không khớp!").build();
dao.update(st);
return Response.ok("Sửa thành công!").build();
}
@RolesAllowed( "ROLE_ADMIN")
@DELETE
@Path("/{id}")
public Response delete(@PathParam("id") String id) {
dao.delete(id);
return Response.ok("Xóa thành công!").build();
}
}
Bước 7: Run application
- Kích chuột phải vào project chọn Run As -> Run on Server -> Tomcat v9.0
- Mở phần mềm Postman để test
GET: /api/students (không yêu cầu login)
POST: /api/students/gettoken (đăng nhập lấy token)
POST: /api/students (thêm sinh viên yêu cầu token kèm theo)
Link download source code bài viết Security trong Restful Webservice sử dụng Jersey 2 để sinh ra JWT
Video
thay lời cảm ơn!
Các bài cũ hơn
- Restful Webservice Upload file kèm dữ liệu JSON sử dụng Jersey trong Java và Oracle (09:47 AM - 27/11/2023)
- Tạo RESTful Web Service trong Java với Jersey và Oracle (10:41 AM - 24/11/2023)
- Phát triển ứng dụng RESTful Web Service trong Java với thư viện Jersey (12:52 PM - 22/11/2023)
- Tổng hợp các câu hỏi phỏng vấn về Spring Core-Spring MVC (09:36 AM - 21/11/2023)
- Microservices sử dụng ASP.NET Core 6 và Deploy với Docker (08:41 AM - 20/11/2023)