-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from wwan13/feature/refactor
docs : add README.md
- Loading branch information
Showing
1 changed file
with
244 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,4 +23,247 @@ repositories { | |
dependencies { | ||
implementation 'com.github.wwan13:winter-security:0.0.2' | ||
} | ||
``` | ||
``` | ||
|
||
## How To Use | ||
|
||
You can find the full example code in | ||
the [repository](https://github.com/wwan13/winter-security-example). | ||
|
||
### 1. Jwt Provider | ||
|
||
If your module includes a login API or requires issuance of jwt tokens, you should use this options. | ||
|
||
**1.1 Configuration** | ||
|
||
```java | ||
|
||
@Configuration | ||
@EnableJwtProvider | ||
public class SecurityConfig implements JwtProviderConfigurer { | ||
|
||
@Override | ||
public void configureSecretKey(SecretKeyRegistry registry) { | ||
registry | ||
.secretKey("d2ludGVyLXNlY3VyaXR5LWV4YW1wbGUK"); | ||
} | ||
|
||
@Override | ||
public void configureJwt(JwtPropertiesRegistry registry) { | ||
registry | ||
.accessTokenValidity(1000000L) | ||
.refreshTokenValidity(3000000L); | ||
} | ||
} | ||
``` | ||
|
||
This is the step to set the information required for JWT token creation. | ||
Enter the secretKey and expiration period for each token. | ||
|
||
<br/> | ||
|
||
```java | ||
|
||
@Payload | ||
public record TokenPayload( | ||
@Subject | ||
long id, | ||
@Roles | ||
Set<String> roles // String roles | ||
) { | ||
} | ||
``` | ||
|
||
Declare the payload that makes up the JWT token as follows. | ||
You can create a JWT token using the payload declared here. | ||
|
||
> If you want to use only one role, you can use a single type rather than a Collection type. | ||
<br/> | ||
|
||
**1.2 Using Jwt Providers** | ||
|
||
Now you can generate and decode JWT tokens like this. | ||
|
||
```java | ||
|
||
@Service | ||
public class TokenService { | ||
|
||
private final TokenGenerator tokenGenerator; | ||
private final TokenDecoder tokenDecoder; | ||
|
||
public TokenService(TokenGenerator tokenGenerator, TokenDecoder tokenDecoder) { | ||
this.tokenGenerator = tokenGenerator; | ||
this.tokenDecoder = tokenDecoder; | ||
} | ||
|
||
public String generateToken(long id, String role) { | ||
TokenPayload payload = new TokenPayload(id, role); | ||
|
||
String accessToken = tokenGenerator.accessToken(payload); | ||
String refreshToken = tokenGenerator.refreshToken(payload); | ||
|
||
return accessToken; | ||
} | ||
|
||
public TokenClaims decodeToken(String token) { | ||
TokenClaims claims = tokenDecoder.decode(token); | ||
|
||
long subject = (long) claims.getSubject(); | ||
Set<String> roles = claims.getRoles(); | ||
boolean isAccessToken = claims.isAccessToken(); | ||
boolean isRefreshToken = claims.isRefreshToken(); | ||
|
||
return claims; | ||
} | ||
} | ||
``` | ||
|
||
Each token can be created using TokenGenerator's `accessToken()` and `refreshToken()`. | ||
And the generated token can be decoded using TokenDecoder. And it contains the token's subject, | ||
roles, and token type. | ||
|
||
<br/> | ||
|
||
### 2. Secure Request | ||
|
||
If your API requests require permission management you should use this. | ||
|
||
**2.1. Configuration** | ||
|
||
```java | ||
|
||
@Configuration | ||
@EnableSecureRequest | ||
public class SecurityConfig implements SecureRequestConfigurer { | ||
|
||
@Override | ||
public void configureSecretKey(SecretKeyRegistry registry) { | ||
registry | ||
.secretKey("d2ludGVyLXNlY3VyaXR5LWV4YW1wbGUK"); | ||
} | ||
|
||
@Override | ||
public void registerAuthPatterns(AuthPatternsRegistry registry) { | ||
registry | ||
.uriPatterns("/api/admin/**") | ||
.allHttpMethods() | ||
.hasRoles("ROLE_ADMIN") | ||
|
||
.uriPatterns("/api/user/**") | ||
.allHttpMethods() | ||
.hasRoles("ROLE_USER") | ||
|
||
.uriPatterns("/api/token") | ||
.httpMethodPost() | ||
.permitAll() | ||
|
||
.elseRequestAuthenticated(); | ||
} | ||
|
||
@Override | ||
public void registerTargetAnnotations(TargetAnnotationsRegistry registry) { | ||
registry | ||
.addSubjectResolveAnnotation(RequestUserCustomId.class); | ||
} | ||
} | ||
``` | ||
|
||
By implementing SecureRequestConfiguirer, you can set access permissions for each API request. | ||
Also, if you have a custom annotation that you would like to use when resolving arguments, you can | ||
register that as well. | ||
|
||
<br/> | ||
|
||
**2.1. Using Secure Requests** | ||
|
||
```java | ||
|
||
@RestController | ||
@RequestMapping("/api") | ||
public class ApiController { | ||
|
||
@GetMapping("/id") | ||
public ResponseEntity<IdResponse> getUserId( | ||
@RequestUserId long id | ||
) { | ||
return ResponseEntity.ok().body(new IdResponse(id)); | ||
} | ||
|
||
@GetMapping("/role") | ||
public ResponseEntity<RoleResponse> getUserRole( | ||
@RequestUserRoles Set<String> roles | ||
) { | ||
return ResponseEntity.ok().body(new RoleResponse(role)); | ||
} | ||
|
||
@GetMapping("/customId") | ||
public ResponseEntity<CustomIdResponse> getCustomUserId( | ||
@RequestUserCustomId long customId | ||
) { | ||
return ResponseEntity.ok().body(new CustomIdResponse(customId)); | ||
} | ||
} | ||
``` | ||
|
||
Now you can get the information of the user who requested the API in a similar way | ||
using `@RequestBody` like this. | ||
|
||
<br/> | ||
|
||
### 3. Additional | ||
|
||
If you want to use both functions at the same time, set them as follows. | ||
|
||
```java | ||
|
||
@RestController | ||
@RequestMapping("/api") | ||
public class ApiController { | ||
|
||
@GetMapping("/id") | ||
public ResponseEntity<IdResponse> getUserId( | ||
@RequestUserId long id | ||
) { | ||
return ResponseEntity.ok().body(new IdResponse(id)); | ||
} | ||
|
||
@GetMapping("/role") | ||
public ResponseEntity<RoleResponse> getUserRole( | ||
@RequestUserRoles String role | ||
) { | ||
return ResponseEntity.ok().body(new RoleResponse(role)); | ||
} | ||
|
||
@GetMapping("/customId") | ||
public ResponseEntity<CustomIdResponse> getCustomUserId( | ||
@RequestUserCustomId long customId | ||
) { | ||
return ResponseEntity.ok().body(new CustomIdResponse(customId)); | ||
} | ||
} | ||
``` | ||
|
||
> JwtPrivider and SecureRequest both include PasswordEncoder and TokenDecoder. Therefore, there is | ||
> no need to use unnecessary JwtPrivider functions for reasons such as refreshToken processing. | ||
<br/> | ||
|
||
### 4. Enjoy Your Programming | ||
|
||
Please contact us via the [email]([email protected]) if an error occurs during use. | ||
|
||
<br/> | ||
|
||
## Contributing | ||
|
||
Contributions are welcome! Please feel free to submit a Pull Request. | ||
|
||
<br/> | ||
|
||
## License | ||
|
||
This project is licensed under the terms of the [apache 2.0] license. | ||
|
||
[apache 2.0]: LICENSE.txt |