通过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接口:
@Entitypublic 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;
}
}
加上当局实体:
@Entitypublic 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