### Entity
com.example.demo.account
package com.example.demo.account;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import javax.persistence.*;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.GrantedAuthority;
@Entity
@Table(name="accounts")
public class Account implements UserDetails{
private static final long serialVersionUID = 1L;
public enum Authority {ROLE_USER, ROLE_MANAGER, ROLE_ADMIN}
@Id
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false)
private String password;
@Column(nullable = false, unique = true)
private String mailAddress;
@Column(nullable = false)
private boolean mailAddressVerified;
@Column(nullable = false)
private boolean enabled;
@Temporal(TemporalType.TIMESTAMP)
private Date createdAt;
@ElementCollection(fetch = FetchType.EAGER)
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private Set<Authority> authorities;
protected Account() {}
public Account(String username, String password, String mailAddress) {
this.username = username;
this.password = password;
this.mailAddress = mailAddress;
this.mailAddressVerified = false;
this.enabled = true;
this.authorities = EnumSet.of(Authority.ROLE_USER);
}
@PrePersist
public void prePersist() {
this.createdAt = new Date();
}
public boolean isAdmin() {
return this.authorities.contains(Authority.ROLE_ADMIN);
}
public void setAdmin(boolean isAdmin) {
if(isAdmin) {
this.authorities.add(Authority.ROLE_MANAGER);
this.authorities.add(Authority.ROLE_ADMIN);
} else {
this.authorities.remove(Authority.ROLE_ADMIN);
}
}
public boolean isManager() {
return this.authorities.contains(Authority.ROLE_MANAGER);
}
public void setManager(boolean isManager) {
if(isManager) {
this.authorities.add(Authority.ROLE_MANAGER);
} else {
this.authorities.remove(Authority.ROLE_MANAGER);
this.authorities.remove(Authority.ROLE_ADMIN);
}
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
for (Authority authority : this.authorities) {
authorities.add(new SimpleGrantedAuthority(authority.toString()));
}
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getMailAddress() {
return mailAddress;
}
public void setMailAddress(String mailAddress) {
this.mailAddress = mailAddress;
}
public boolean isMailAddressVerified() {
return mailAddressVerified;
}
public void setMailAddressVerified(boolean mailAddressVerified) {
this.mailAddressVerified = mailAddressVerified;
}
public Date getCreatedAt() {
return createdAt;
}
}
Repository
package com.example.demo.account;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface AccountRepository extends CrudRepository<Account, Long>{
public Account findByUsername(String username);
}
Service
package com.example.demo.account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AccountService implements UserDetailsService {
@Autowired
private AccountRepository repository;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public Account loadUserByUsername(String username) throws UsernameNotFoundException {
if(username == null || "".equals(username)) {
throw new UsernameNotFoundException("Username is empty");
}
Account user = repository.findByUsername(username);
if(user == null) {
throw new UsernameNotFoundException("User not found: " + username);
}
return user;
}
@Transactional
public void registerAdmin(String username, String password, String mailAddress) {
Account user = new Account(username, passwordEncoder.encode(password), mailAddress);
user.setAdmin(true);
repository.save(user);
}
@Transactional
public void registerManager(String username, String password, String mailAddress) {
Account user = new Account(username, passwordEncoder.encode(password), mailAddress);
user.setManager(true);
repository.save(user);
}
@Transactional
public void registerUser(String username, String password, String mailAddress) {
Account user = new Account(username, passwordEncoder.encode(password), mailAddress);
repository.save(user);
}
}
AuthoController.java
package com.example.demo.account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class AuthController {
@RequestMapping("/")
public String index() {
return "redirect:/top";
}
@GetMapping("/login")
public String login() {
return "login";
}
@PostMapping("/login")
public String loginPost() {
return "redirect:/login-error";
}
@GetMapping("/login-error")
public String loginError(Model model) {
model.addAttribute("loginError", true);
return "login";
}
@RequestMapping("/top")
public String top() {
return "/top";
}
}
WebSecurityConfig.java
package com.example.demo;
import com.example.demo.account.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AccountService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login", "/login-error").permitAll()
.antMatchers("/**").hasRole("USER")
.and()
.formLogin()
.loginPage("/login").failureUrl("/login-error");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userService)
.passwordEncoder(passwordEncoder());
userService.registerAdmin("admin", "secret", "admin@localhost");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
login.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>Login page</title>
<style>
.alert-danger{color:red;}
</style>
</head>
<body>
<h2>ログイン画面</h2>
<form th:action="@{/login}" method="post">
<div th:if="${session['SPRING_SECURITY_LAST_EXCEPTION']} != null" class="alert-danger">
<span th:text="ユーザ名またはパスワードに誤りがあります"></span>
</div>
<div style="width:160px;"><label for="username">ユーザ名:</label></div>
<input type="text" name="username" autofocus="autofocus">
<br>
<div style="width:160px;"><label for="password">パスワード:</label></div>
<input type="password" name="password" />
<br>
<p><input type="submit" value="ログイン"></p>
</body>
</html>
top.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8" />
<title>メニュー画面</title>
</head>
<body>
<h2>ログイン画面</h2>
<div th:fragment="logout" sec:authorize="isAuthenticated()">
<p>こんにちは:
<span sec:authentication="name"></span>さん</p>
<p>mail:
<span sec:authentication="principal.mailAddress"></span></p>
<p>権限:
<span sec:authentication="principal.authorities"></span></p>
<form action="#" th:action="@{/logout}" method="post">
<input type="submit" value="ログアウト">
</form>
</div>
</body>
</html>
application.properties
spring.jpa.database=POSTGRESQL
spring.datasource.url=jdbc:postgresql://localhost:5432/test
spring.datasource.username=root
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
hibernate.properties
hibernate.jdbc.lob.non_contextual_creation = true
test=> select * from accounts;
username | created_at | enabled | mail_address | mail_address_verified | password
———-+————+———+—————–+———————–+————————————————————–
admin | | t | admin@localhost | f | $2a$10$19UBN8MoIHBihXXDs2uyreHU4DlAow7jNfUwtChyAw6pp5THYM8N.
(1 row)
あああああああああああ
AccountService.javaで登録してんのか。
@Transactional
public void registerAdmin(String username, String password, String mailAddress) {
Account user = new Account(username, passwordEncoder.encode(password), mailAddress);
user.setAdmin(true);
repository.save(user);
}
なるほど、
spring.jpa.hibernate.ddl-auto=update で、自動でテーブルが作成されんのか。。
insert into accounts (username, enabled, mail_address, mail_address_verified, password) values
(‘user1′,TRUE,’user1@gmail.com’, FALSE,’$2a$10$BuoyNf/vQZB5cS.eCEtW7uHtFTMq0SwLKXblcOeGCIJCpqeCnQH2S’),
(‘user2′,TRUE,’user2@gmail.com’, FALSE,’$2a$10$BuoyNf/vQZB5cS.eCEtW7uHtFTMq0SwLKXblcOeGCIJCpqeCnQH2S’);
insert into account_authorities (account_username, authorities) values
(‘user1′,’ROLE_USER’);

やべえええええええええええええ
Spring Securityできたやんか🔥🔥🔥🔥
他にやりたい事もあるけど、Javaでなんか作るかー。