通过Vaadin登录的Spring Boot安全性

我尝试基于Spring Boot" title="Spring Boot">Spring Boot(1.2.7.RELEASE)和Vaadin(7.6.3)构建一个应用程序。我的问题是我无法将Spring

Security与Vaadin集成。我想要自定义的Vaadin构建的LoginScreen和Spring Security控件。我的项目设置如下:

@Configuration

@EnableWebSecurity

public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

@Override

protected void configure(HttpSecurity http) throws Exception {

http.csrf().disable().

exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")).accessDeniedPage("/accessDenied")

.and().authorizeRequests()

.antMatchers("/VAADIN/**", "/PUSH/**", "/UIDL/**", "/login", "/login/**", "/error/**", "/accessDenied/**", "/vaadinServlet/**").permitAll()

.antMatchers("/authorized", "/**").fullyAuthenticated();

}

}

这是我的Vaadin登录UI

 @SpringUI(path = "/login")

@Title("LoginPage")

@Theme("valo")

public class LoginUI extends UI {

TextField user;

PasswordField password;

Button loginButton = new Button("Login", this::loginButtonClick);

private static final String username = "username";

private static final String passwordValue = "test123";

@Override

protected void init(VaadinRequest request) {

setSizeFull();

user = new TextField("User:");

user.setWidth("300px");

user.setRequired(true);

user.setInputPrompt("Your username");

password = new PasswordField("Password:");

password.setWidth("300px");

password.setRequired(true);

password.setValue("");

password.setNullRepresentation("");

VerticalLayout fields = new VerticalLayout(user, password, loginButton);

fields.setCaption("Please login to access the application");

fields.setSpacing(true);

fields.setMargin(new MarginInfo(true, true, true, false));

fields.setSizeUndefined();

VerticalLayout uiLayout = new VerticalLayout(fields);

uiLayout.setSizeFull();

uiLayout.setComponentAlignment(fields, Alignment.MIDDLE_CENTER);

setStyleName(Reindeer.LAYOUT_BLUE);

setFocusedComponent(user);

setContent(uiLayout);

}

public void loginButtonClick(Button.ClickEvent e) {

//authorize/authenticate user

//tell spring that my user is authenticated and dispatch to my mainUI

}

}

当我启动应用程序时,spring会将我重定向到登录UI,这很好。

但是我不知道如何根据spring安全机制对用户进行身份验证并将其分发到我的mainUI。

我也面临着csrf令牌的问题,如果我不禁用csrf,我会得到crfs令牌为null异常。我发现了很多解决这些问题的示例,但Vaadin并没有提供解决方案。

感谢帮助。

回答:

经过一周的努力和研究,我得以使这项工作奏效。这非常累人,因为互联网上有很多信息和解决方案,其中大多数使用基于xml的配置或基于JSP表单的登录,直到现在,如果没有使用Vaadin框架创建xml配置文件的xml配置文件,我将找不到其他解决方案。自定义登录页面。

我不能保证这是最佳做法或最简单的解决方案。此外,我并未评估它的每个部分,据我所知,登录机制仍然有效,但是可能存在一些尚未发现的问题。

也许它将对遇到相同问题的人有所帮助,所以我将在此处发布答案。

首先我的securityConfig:

@Resource(name = "authService")

private UserDetailsService userDetailsService;

@Override

protected void configure(HttpSecurity http) throws Exception {

http.csrf().disable().

exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")).accessDeniedPage("/accessDenied")

.and().authorizeRequests()

.antMatchers("/VAADIN/**", "/PUSH/**", "/UIDL/**", "/login", "/login/**", "/error/**", "/accessDenied/**", "/vaadinServlet/**").permitAll()

.antMatchers("/authorized", "/**").fullyAuthenticated();

}

@Bean

public DaoAuthenticationProvider createDaoAuthenticationProvider() {

DaoAuthenticationProvider provider = new DaoAuthenticationProvider();

provider.setUserDetailsService(userDetailsService);

provider.setPasswordEncoder(passwordEncoder());

return provider;

}

@Bean

public BCryptPasswordEncoder passwordEncoder() {

return new BCryptPasswordEncoder();

}

您必须禁用crsf,但这没问题,因为vaadin具有自己的crsf保护。

此外,您还需要允许一些这样的URI可以vaadin访问其资源:/VAADIN/**是绝对必要的,我也reccommend允许/vaadinServlet/**/PUSH/**/HEARTBEAT/**,但是这取决于你用什么Vaadin的部分。

第二我的UserDetailsService

@Service("authService")

public class AuthService implements UserDetailsService {

@Autowired

CustomUserRepository userRepository;

@Override

public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {

CustomUser user = userRepository.findCustomUserByUserName(userName);

return user;

}

}

DaoAuthenticationProvider使用UserDetails

loadUserByUserName方法得到一个类,它实现的目的UserDetails接口。请注意,中描述的每个属性都UserDetailsInterface不能为null,否则后面的内容会NullPointerException引发异常DaoAuthenticationProvider

我创建了一个JPA实体,该实体实现了UserDetails接口:

@Entity

public class CustomUser implements UserDetails {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

Long id;

@ManyToMany(fetch = FetchType.EAGER)

Collection<Authorities> authorities;

String password;

String userName;

Boolean accountNonExpired;

Boolean accountNonLocked;

Boolean credentialsNonExpired;

Boolean enabled;

@Autowired

@Transient

BCryptPasswordEncoder passwordEncoder;

@Override

public Collection<? extends GrantedAuthority> getAuthorities() {

return authorities;

}

@Override

public String getPassword() {

return password;

}

@Override

public String getUsername() {

return userName;

}

@Override

public boolean isAccountNonExpired() {

return accountNonExpired;

}

@Override

public boolean isAccountNonLocked() {

return accountNonLocked;

}

@Override

public boolean isCredentialsNonExpired() {

return credentialsNonExpired;

}

@Override

public boolean isEnabled() {

return enabled;

}

public void setId(Long id) {

this.id = id;

}

public void setAuthorities(Collection<Authorities> authorities) {

this.authorities = authorities;

}

public void setPassword(String password) {

this.password = passwordEncoder.encode(password);

}

public void setUserName(String userName) {

this.userName = userName;

}

public void setAccountNonExpired(Boolean accountNonExpired) {

this.accountNonExpired = accountNonExpired;

}

public void setAccountNonLocked(Boolean accountNonLocked) {

this.accountNonLocked = accountNonLocked;

}

public void setCredentialsNonExpired(Boolean credentialsNonExpired) {

this.credentialsNonExpired = credentialsNonExpired;

}

public void setEnabled(Boolean enabled) {

this.enabled = enabled;

}

}

加上当局实体:

@Entity

public class Authorities implements GrantedAuthority {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

Long id;

String authority;

@Override

public String getAuthority() {

return authority;

}

public void setAuthority(String authority) {

this.authority = authority;

}

}

显然,必须先在数据库中存储一些用户数据,然后身份验证才能起作用。

在Vaadin中,我无法通过使用一个具有不同视图的UI来使其工作,因此我最终使用了两个UI,一个用于登录,另一个用于主应用程序。

在Vaadin中,我可以在类注释中设置URI路径:

@SpringUI(path = "/login")

@Title("LoginPage")

@Theme("valo")

public class LoginUI extends UI {

//...

}

使用此配置,我的登录屏幕位于localhost:port/login ,我的主应用程序位于localhost:port/main

我以编程方式在我的loginUI中的button.click方法中登录用户:

Authentication auth = new UsernamePasswordAuthenticationToken(userName.getValue(),password.getValue());

Authentication authenticated = daoAuthenticationProvider.authenticate(auth);

SecurityContextHolder.getContext().setAuthentication(authenticated);

//redirect to main application

getPage().setLocation("/main");

希望对您有所帮助。

以上是 通过Vaadin登录的Spring Boot安全性 的全部内容, 来源链接: utcz.com/qa/399771.html

回到顶部