-Authentication 을 파라미터로 선언해주면 인증정보가 알아서 담긴다. - getName() 으로 구한 유저 이름을 board 정보와 함께 boardService에 전달
@Service
public class BoardService {
@Autowired
private BoardRepository boardRepository;
@Autowired
private UserRepository userRepository;
public Board save(String username, Board board){
//1. 넘겨받은 username을 가지고 user의 id 조회
User user = userRepository.findByUsername(username);
board.setUser(user);
return boardRepository.save(board);
}
}
BoardService에서는 컨트롤러에서 넘겨받은 username을 가지고 user 정보를 조회한다. -> 그러기위해선 UserRepository 에 관련 메소드를 만들어줘야한다.
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username); //컬럼이름에 일치하는 사용자 데이터를 가져온다.
}
@Entity //db연동을 위한 모델클래스임을 명시
@Data
public class User {
...
@OneToMany(mappedBy = "user")
private List<Board> boards = new ArrayList<>();
}
- mappedBy 로 Board 클래스의 user를 적어준다. - onetomany, manytoone 관계에서 보통 many쪽 에서 소유하는쪽을 @JoinColumn을 써서 적어준다
이후 WebSecurityConfigurerAdapter을 상속받은 WebSecurityConfig클래스를 만들어준다. *@Configuration 을 선언한 클래스에선 @Bean을 관리할 수 있다.
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//application.properties의 dataSource가져옴
@Autowired
private DataSource dataSource;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/account/register", "/css/**").permitAll() //누구나 접근할수 있는 url
.anyRequest().authenticated() //어떤 요청이라도 authenticated 돼야한다.
.and()
.formLogin() //authenticated안된 상태에서 다른 페이지 가려하면
.loginPage("/account/login") //login페이지로 redirect된다.
.permitAll() //login 페이지는 누구라도 접근가능
.and()
.logout()
.permitAll();
}
}
테이블 ERD는 다음과 같다. user 테이블에는 id, username, password, enabled(활성화여부) role 테이블은 id, name(권한명) user와 role은 many-to-many 관계이므로 user_role 테이블을 만들어서 관계형 테이블을 만든다.
user_id 와 role_id는 각각 pk이다. 외래키 설정을 통해 무결성을 보장하도록 한다.
@Entity //db연동을 위한 모델클래스임을 명시
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //Autoincrement 설정, IDENTITY가 많이 사용
private Long id;
private String username;
private String password;
private Boolean enabled;
//user에 해당하는 권한이 알아서 조회돼서, roles에 담긴다.
@ManyToMany
@JoinTable(
name = "user_role",
joinColumns = @JoinColumn(name="user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private List<Role> roles = new ArrayList<>();
}
@Entity //db연동을 위한 모델클래스임을 명시
@Data
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //Autoincrement 설정, IDENTITY가 많이 사용
private Long id;
private String name; //권한명
@ManyToMany(mappedBy = "roles") //mappedBy: User클래스에 있는 컬럼명이 된다.
private List<User> users;
}
==UserRepository 생성==
public interface UserRepository extends JpaRepository<User, Long> {
}
==UserService 생성==
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
//유저 저장
public User save(User user){
// 1.비밀번호 인코딩
String encodedPassword = passwordEncoder.encode(user.getPassword());
user.setPassword(encodedPassword);
// 2.회원 활성화 여부 - 기본적으로 enabled로 설정
user.setEnabled(true);
// 3. role정보 추가
Role role = new Role();
role.setId(1L);
user.getRoles().add(role);
return userRepository.save(user);
}
}
- DI를 통해 UserRepository 객체를 받아온다. - WebSecurityConfig에 Bean으로 있는 PasswordEncoder를 DI로 가져와서 사용자가 전달한 비밀번호 인코딩한다.
sec:authorize="!isAuthenticated() : isAuthenticated()은 로그인 되었을때니까 ! 붙여준다. sec:authentication="name" : 로그인 한 사용자의 name 조회 sec:authentication="principal.authorities" :로그인 한 사용자의 권한 조회
N개의 문자열 데이터를 입력받아 앞에서 읽을 때나 뒤에서 읽을 때나 같은 경우(회문 문자열) 이면 YES를 출력하고 회문 문자열이 아니면 NO를 출력하는 프로그램을 작성한다. 단 회문을 검사할 때 대소문자를 구분하지 않습니다.
▣ 입력설명 첫 줄에 정수 N(1<=N<=20)이 주어지고, 그 다음 줄부터 N개의 단어가 입력된다. 각 단어의 길이는 100을 넘지 않는다.
▣ 출력설명 각 줄에 해당 문자열의 결과를 YES 또는 NO로 출력한다.
▣ 입력예제 1 5 level moon abcba soon gooG
▣ 출력예제 1 #1 YES #2 NO #3 YES #4 NO #5 YES
내 풀이
import sys
sys.stdin=open("input.txt", "rt")
n = int(input())
for i in range(n):
a = list(input().lower())
lenA = len(a) #리스트 길이
count =0
for j in range(lenA // 2 ):
if a[j] == a[lenA-1-j]:
continue
else:
count+=1
if count ==0:
print('#',i+1, ' YES')
else:
print('#',i+1, ' NO')
설명: - 입력값 n의 크기 만큼 반복문을 돈다. 반복하면서 입력값 문자열 a를 소문자 형태로 바꾸고 리스트로 바꿔준다. - lenA를 통해 리스트의 길이를 구해준다. - 변수 count를 선언한다. 여기서 카운트란 앞 뒤 수가 다른 경우의 수를 말한다. - 앞 뒤 숫자를 비교하기때문에 반복분은 리스트 길이의 절반, 즉 2로 나눈 몫 횟수로 돌려준다. - 반복문을 돌며 j번째 인덱스 값과 리스트길이-1-j 의 인덱스 값을 비교해준다. - 만약 앞, 뒤 값이 같으면 continue해서 다음 앞뒤를 비교해주고, 다르면 count에 1을 추가해준다. - 결과적으로 count가 0이면 앞뒤가 모두 같으므로 YES를 0이 아니면 NO를 출력해준다.
다른 풀이
import sys
sys.stdin=open("input.txt", "rt")
n = int(input())
for i in range(n):
s = input().upper()
size = len(s)
for j in range(size//2):
if s[j] != s[-1-j]:
print('#%d NO' %(i+1))
break
print('#%d YES' %(i+1))
설명 - 전반적으로 내 풀이와 크게 다르진 않다. - 다만 2중 for문을 돌때 인덱스 값 세팅을 다르게했다. ex) s[-1]: 뒤에서부터 첫번째 인덱스값 - 또 굳이 리스트로 만들지 않고 문자열의 인덱스 값으로 바로 비교를 했다. (코드수를 줄일 수 있어 더 경제적이다.)
1에서부터 6까지의 눈을 가진 3개의 주사위를 던져서 다음과 같은 규칙에 따라 상금을 받는 게 임이 있다.
규칙(1) 같은 눈이 3개가 나오면 10,000원+(같은 눈)*1,000원의 상금을 받게 된다. 규칙(2) 같은 눈이 2개만 나오는 경우에는 1,000원+(같은 눈)*100원의 상금을 받게 된다. 규칙(3) 모두 다른 눈이 나오는 경우에는 (그 중 가장 큰 눈)*100원의 상금을 받게 된다.
예를 들어, 3개의 눈 3, 3, 6이 주어지면 상금은 1,000+3*100으로 계산되어 1,300원을 받게 된 다. 또 3개의 눈이 2, 2, 2로 주어지면 10,000+2*1,000 으로 계산되어 12,000원을 받게 된다. 3개의 눈이 6, 2, 5로 주어지면 그 중 가장 큰 값이 6이므로 6*100으로 계산되어 600원을 상금 으로 받게 된다.
N 명이 주사위 게임에 참여하였을 때, 가장 많은 상금을 받은 사람의 상금을 출력하는 프로그램 을 작성하시오
▣ 입력설명 첫째 줄에는 참여하는 사람 수 N(2<=N<=1,000)이 주어지고 그 다음 줄부터 N개의 줄에 사람 들이 주사위를 던진 3개의 눈이 빈칸을 사이에 두고 각각 주어진다.
▣ 출력설명 첫째 줄에 가장 많은 상금을 받은 사람의 상금을 출력한다.
▣ 입력예제 1 3 3 3 6 2 2 2 6 2 5
▣ 출력예제 1 12000
내 풀이
import sys
n = int(input())
maxPrice = 0
price = 0
for _ in range(n):
a = list(map(int, input().split())) #주사위 눈 3개 가져오기
if a[0] == a[1] == a[2]:
price = 10000 + a[0]*1000
elif a[0] == a[1] != a[2]:
price = 1000 + a[0]*100
elif a[1] == a[2] != a[0]:
price = 1000 + a[0]*100
elif a[0] == a[2] != a[1]:
price = 1000 + a[0]*100
else:
price = max(a)*100
if price > maxPrice:
maxPrice = price
print(maxPrice)
다른 풀이
import sys
sys.stdin=open("input.txt", "rt")
n = int(input())
res=0
for i in range(n):
tmp = input().split()
tmp.sort() #문자열 오름차순
a,b,c = map(int, tmp)
if a==b and b==c: #3개 모두 같을때
money=10000+a*1000
elif a==b or a==c: #2개가 같을때
money=1000+(a*100)
elif b==c: #2개가 같을때
money=1000+(b*100)
else:
money=c*100 #다 다를때 - 가장 큰 c기준
if money>res:
res=money
print(res)