Skip to content

Commit

Permalink
Merge pull request hs-web#90 from hs-web/3.0.x
Browse files Browse the repository at this point in the history
3.0.1
  • Loading branch information
zhou-hao authored Oct 10, 2018
2 parents 995200d + 27e7260 commit 51f1308
Show file tree
Hide file tree
Showing 166 changed files with 706 additions and 321 deletions.
2 changes: 1 addition & 1 deletion hsweb-authorization/hsweb-authorization-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>hsweb-authorization</artifactId>
<groupId>org.hswebframework.web</groupId>
<version>3.0.0</version>
<version>3.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
package org.hswebframework.web.authorization.define;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hswebframework.web.authorization.Authentication;
import org.hswebframework.web.boost.aop.context.MethodInterceptorContext;

/**
* 权限控制上下文
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class AuthorizingContext {
private AuthorizeDefinition definition;

Expand Down
25 changes: 13 additions & 12 deletions hsweb-authorization/hsweb-authorization-basic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,18 @@ where name like ? or full_name like
where u_id in(?,?,?) and (name like ? or full_name like)
```

## 授权登录接口
http接口: `POST /authorize/login`, 登录接口支持2种`content-type`,`application/json`(Json RequestBody方式)和`application/x-www-form-urlencoded`(表单方式),
请在调用等时候指定对应等`content-type`.必要参数: `username``password`.

⚠️注意: 此接口只实现了简单的登录逻辑,不过会通过发布各种事件来实现自定义的逻辑处理.

1. `AuthorizationDecodeEvent` 在接收到登录请求之后触发,如果在登录前对用户名密码进行里加密,可以通过监听此事件实现对用户名密码的解密操作
2. `AuthorizationBeforeEvent``AuthorizationDecodeEvent`事件完成后触发,可通过监听此事件并获取请求参数,实现验证码功能
3. `AuthorizationSuccessEvent` 在授权成功后触发.注意: 权限控制模块也是通过监听此事件来完成授权
4. `AuthorizationFailedEvent` 授权失败时触发.当发生过程中异常时触发此事件

什么? 还不知道如何监听事件? [快看这里](https://github.com/hs-web/hsweb-framework/wiki/事件驱动)

# 会话状态
此模块默认使用sessionId绑定用户信息。还可以使用 [jwt](../hsweb-authorization-jwt) 方式

# 跨域设置
修改application.yml
```yaml
hsweb:
cors:
enabled: on
allowed-origins: "*"
allowed-methods: "*"
allowed-headers: "*"

```
2 changes: 1 addition & 1 deletion hsweb-authorization/hsweb-authorization-basic/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>hsweb-authorization</artifactId>
<groupId>org.hswebframework.web</groupId>
<version>3.0.0</version>
<version>3.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
import org.hswebframework.web.authorization.basic.aop.AopMethodAuthorizeDefinitionParser;
import org.hswebframework.web.authorization.basic.embed.EmbedAuthenticationManager;
import org.hswebframework.web.authorization.basic.handler.DefaultAuthorizingHandler;
import org.hswebframework.web.authorization.basic.handler.UserAllowPermissionHandler;
import org.hswebframework.web.authorization.basic.handler.access.DefaultDataAccessController;
import org.hswebframework.web.authorization.basic.web.*;
import org.hswebframework.web.authorization.basic.web.session.UserTokenAutoExpiredListener;
import org.hswebframework.web.authorization.token.UserTokenManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
Expand Down Expand Up @@ -75,6 +77,11 @@ public AuthenticationManager embedAuthenticationManager() {
return new EmbedAuthenticationManager();
}

@Bean
public UserAllowPermissionHandler userAllowPermissionHandler() {
return new UserAllowPermissionHandler();
}

@Bean
public UserOnSignIn userOnSignIn(UserTokenManager userTokenManager) {
return new UserOnSignIn(userTokenManager);
Expand Down Expand Up @@ -119,4 +126,16 @@ public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}

@Configuration
@ConditionalOnProperty(prefix = "hsweb.authorize", name = "basic-authorization", havingValue = "true")
@ConditionalOnClass(UserTokenForTypeParser.class)
public static class BasicAuthorizationConfiguration {
@Bean
public BasicAuthorizationTokenParser basicAuthorizationTokenParser(AuthenticationManager authenticationManager,
UserTokenManager tokenManager) {
return new BasicAuthorizationTokenParser(authenticationManager, tokenManager);
}

}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package org.hswebframework.web.authorization.starter;
package org.hswebframework.web.authorization.basic.configuration;

import org.apache.commons.codec.binary.Base64;
import org.hswebframework.web.authorization.Authentication;
import org.hswebframework.web.authorization.AuthenticationManager;
import org.hswebframework.web.authorization.basic.web.AuthorizedToken;
import org.hswebframework.web.authorization.basic.web.ParsedToken;
import org.hswebframework.web.authorization.basic.web.UserTokenForTypeParser;
import org.hswebframework.web.authorization.simple.PlainTextUsernamePasswordAuthenticationRequest;
import org.hswebframework.web.authorization.token.UserToken;
import org.hswebframework.web.authorization.token.UserTokenManager;
import org.hswebframework.web.entity.authorization.UserEntity;
import org.hswebframework.web.service.authorization.UserService;

import javax.servlet.http.HttpServletRequest;

public class BasicAuthorizationTokenParser implements UserTokenForTypeParser {

private UserService userService;
private AuthenticationManager authenticationManager;

private UserTokenManager userTokenManager;

Expand All @@ -21,8 +23,8 @@ public String getTokenType() {
return "basic";
}

public BasicAuthorizationTokenParser(UserService userService, UserTokenManager userTokenManager) {
this.userService = userService;
public BasicAuthorizationTokenParser(AuthenticationManager authenticationManager, UserTokenManager userTokenManager) {
this.authenticationManager = authenticationManager;
this.userTokenManager = userTokenManager;
}

Expand Down Expand Up @@ -56,12 +58,12 @@ public String getType() {
}
if (usernameAndPassword.contains(":")) {
String[] arr = usernameAndPassword.split("[:]");
UserEntity user = userService.selectByUserNameAndPassword(arr[0], arr[1]);
if (user != null) {
Authentication authentication = authenticationManager.authenticate(new PlainTextUsernamePasswordAuthenticationRequest(arr[0], arr[1]));
if (authentication != null) {
return new AuthorizedToken() {
@Override
public String getUserId() {
return user.getId();
return authentication.getUser().getId();
}

@Override
Expand All @@ -77,7 +79,7 @@ public String getType() {
@Override
public long getMaxInactiveInterval() {
//60分钟有效期
return 60*60*1000L;
return 60 * 60 * 1000L;
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.hswebframework.web.validate.ValidationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
Expand All @@ -22,6 +24,7 @@
* @since 3.0.0-RC
*/
@ConfigurationProperties(prefix = "hsweb")
@Order(Ordered.HIGHEST_PRECEDENCE)
public class EmbedAuthenticationManager implements AuthenticationManager {

private Map<String, Authentication> authentications = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public class EmbedAuthenticationProperties {

private List<PermissionInfo> permissions = new ArrayList<>();

private Map<String, List<String>> permissionsSimple = new HashMap<>();

@Getter
@Setter
public static class PermissionInfo {
Expand All @@ -77,7 +79,9 @@ public Authentication toAuthentication(DataAccessConfigBuilderFactory factory) {
user.setType(type);
authentication.setUser(user);
authentication.setRoles((List) roles);
List<Permission> permissionList = permissions.stream()
List<Permission> permissionList = new ArrayList<>();

permissionList.addAll(permissions.stream()
.map(info -> {
SimplePermission permission = new SimplePermission();
permission.setId(info.getId());
Expand All @@ -88,7 +92,16 @@ public Authentication toAuthentication(DataAccessConfigBuilderFactory factory) {
.build()).collect(Collectors.toSet()));
return permission;

}).collect(Collectors.toList());
})
.collect(Collectors.toList()));

permissionList.addAll(permissionsSimple.entrySet().stream()
.map(entry -> {
SimplePermission permission = new SimplePermission();
permission.setId(entry.getKey());
permission.setActions(new HashSet<>(entry.getValue()));
return permission;
}).collect(Collectors.toList()));

authentication.setPermissions(permissionList);
return authentication;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package org.hswebframework.web.authorization.basic.handler;

import lombok.Getter;
import lombok.Setter;
import org.hswebframework.web.authorization.define.AuthorizingContext;
import org.hswebframework.web.authorization.define.HandleType;
import org.hswebframework.web.authorization.listener.event.AuthorizingHandleBeforeEvent;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.event.EventListener;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.ClassUtils;
import org.springframework.util.PathMatcher;

import java.util.*;

/**
* <pre>
* hsweb:
* authorize:
* allows:
* users:
* admin: *
* guest: **.query*
* roles:
* admin: *
*
* </pre>
*
* @author zhouhao
* @since 3.0.1
*/
@ConfigurationProperties("hsweb.authorize")
public class UserAllowPermissionHandler {

@Getter
@Setter
private Map<String, Map<String, String>> allows = new HashMap<>();

private PathMatcher pathMatcher = new AntPathMatcher(".");

@EventListener
public void handEvent(AuthorizingHandleBeforeEvent event) {

if (allows.isEmpty() || event.getHandleType() == HandleType.DATA) {
return;
}
AuthorizingContext context = event.getContext();

// class full name.method
String path = ClassUtils.getUserClass(context.getParamContext()
.getTarget())
.getName().concat(".")
.concat(context.getParamContext()
.getMethod().getName());

String userId = context.getAuthentication().getUser().getId();
boolean allow;
allow = Optional.ofNullable(allows.get("users"))
.map(users -> users.get(userId))
.filter(pattern -> "*".equals(pattern) || pathMatcher.match(pattern, path))
.isPresent();
if (allow) {
event.setAllow(true);
return;
}
allow = context.getAuthentication()
.getRoles()
.stream()
.map(role -> allows.getOrDefault("roles", Collections.emptyMap()).get(role.getId()))
.filter(Objects::nonNull)
.anyMatch(pattern -> "*".equals(pattern) || pathMatcher.match(pattern, path));
if (allow) {
event.setAllow(true);
return;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
Expand Down Expand Up @@ -77,9 +78,8 @@ public ResponseMessage<Authentication> me(@ApiParam(hidden = true) Authenticatio
public ResponseMessage<Map<String, Object>> authorize(@ApiParam(example = "{\"username\":\"admin\",\"password\":\"admin\"}")
@RequestBody Map<String, String> parameter) {

return doLogin(Objects.requireNonNull(parameter.get("username"), "用户名不能为空")
, Objects.requireNonNull(parameter.get("password"), "密码不能为空")
, parameter);

return doLogin(parameter.get("username"), parameter.get("password"), parameter);
}

@PostMapping(value = "/login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
Expand All @@ -93,6 +93,9 @@ public ResponseMessage<Map<String, Object>> authorize(@RequestParam @ApiParam("

@SneakyThrows
protected ResponseMessage<Map<String, Object>> doLogin(String username, String password, Map<String, ?> parameter) {
Assert.hasLength(username, "用户名不能为空");
Assert.hasLength(password, "密码不能为空");

AuthorizationFailedEvent.Reason reason = AuthorizationFailedEvent.Reason.OTHER;
Function<String, Object> parameterGetter = parameter::get;
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.hswebframework.web.authorization.starter;
package org.hswebframework.web.authorization;

import org.hswebframework.web.authorization.basic.configuration.EnableAopAuthorize;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.test.context.web.WebAppConfiguration;

Expand All @@ -9,6 +10,7 @@
*/
@SpringBootApplication
@WebAppConfiguration
@EnableAopAuthorize
public class TestApplication {

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.hswebframework.web.authorization.basic.embed

import org.hswebframework.web.authorization.Authentication
import org.hswebframework.web.authorization.AuthenticationManager
import org.hswebframework.web.authorization.TestApplication
import org.hswebframework.web.authorization.simple.PlainTextUsernamePasswordAuthenticationRequest
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
Expand Down Expand Up @@ -30,6 +31,7 @@ class EmbedAuthenticationManagerTest extends Specification {
authentication.getUser() != null
authentication.getUser().getName() == "超级管理员"
authentication.hasPermission("user-manager", "query")
authentication.hasPermission("test", "query")
authentication.getPermission("user-manager") != null
authentication.hasRole("user")
authentication.getPermission("user-manager")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.hswebframework.web.authorization.basic.handler;

import org.hswebframework.web.authorization.annotation.Authorize;
import org.hswebframework.web.controller.message.ResponseMessage;

/**
* @author zhouhao
* @since 3.0.1
*/
public class TestController {

public ResponseMessage<String> query() {
return ResponseMessage.ok();
}

public ResponseMessage<String> update() {
return ResponseMessage.ok();
}

public ResponseMessage<String> delete() {
return ResponseMessage.ok();
}

}
Loading

0 comments on commit 51f1308

Please sign in to comment.