1:添加依赖:
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2:创建验证service集成UserDetailService
package com.qingwenwei.security; import java.util.ArrayList;
import java.util.List; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import com.qingwenwei.persistence.model.User;
import com.qingwenwei.service.UserService;
import org.springframework.stereotype.Service;
//授权认证
@Service
public class MyUserDetailsService implements UserDetailsService{ Logger logger = LogManager.getLogger(MyUserDetailsService.class);
@Autowired
private UserService userService; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
logger.debug("得到用户");
User user = this.userService.findByUsername(username); //加密之后的密码。才能进行下面的授权认证。
logger.debug(user.getUsername()+"密码"+user.getPassword()); //加密之后的密码。
if(null == user) {
throw new UsernameNotFoundException("Can't find user by username: " + username);
} List<SimpleGrantedAuthority> grantedAuthorities = new ArrayList<>();
// grant roles to user
for (String role : user.getRolesSet()) {
logger.debug(role);
grantedAuthorities.add(new SimpleGrantedAuthority(role));
}
// user.setGrantedAuthorities(authorities); //用于登录时 @AuthenticationPrincipal 标签取值
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities);
}
}
3:进行配置
package com.qingwenwei.security; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Autowired
MyUserDetailsService myUserDetailsService;
// @Bean
// UserDetailsService myUserDetailsService() { // register userDetailsService
// return new MyUserDetailsService();
// } @Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
// authenticationProvider.setUserDetailsService(this.myUserDetailsService());
authenticationProvider.setUserDetailsService(myUserDetailsService);
authenticationProvider.setPasswordEncoder(this.bCryptPasswordEncoder());
return authenticationProvider;
} @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { //全局配置
// auth.inMemoryAuthentication() //內存中存在的验证
// .withUser("t").password("t").roles("USER")
// .and()
// .withUser("admin").password("admin").roles("ADMIN"); auth.userDetailsService(myUserDetailsService).passwordEncoder(this.bCryptPasswordEncoder());
// auth.userDetailsService(myUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
// auth.authenticationProvider(this.authenticationProvider()); // different approach
} @Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/user/settings").authenticated() // order matters
.antMatchers("/", "/js/**", "/css/**","/avatar/**", "/images/**", "/fonts/**", "/bootstrap-select/**", "/bootstrap-datetimepicker/**", "/custom/**", "/daterangepicker/**", "/chartjs/**").permitAll() // these paths are configure not to require any authentication
.antMatchers("/post/**").permitAll() // all posts are allowed to be viewed without authentication
.antMatchers("/user/**").permitAll() // all user profiles are allowed to be viewed without authentication
.antMatchers("/category/**").permitAll() // all categories are allowed to be viewed without authentication
.antMatchers("/user/registration").permitAll()
.antMatchers("/avatar/**").permitAll() // temp
.antMatchers("/avatar1/**").permitAll() // temp
.anyRequest().authenticated() // every request requires the user to be authenticated
.and()
.formLogin()
.loginPage("/user/login")
.permitAll() // login URL can be accessed by anyone
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutSuccessUrl("/?logout")
.permitAll();
}
}
4:userController.java
package com.qingwenwei.web.controller; import com.qingwenwei.exception.BadRequestException;
import com.qingwenwei.exception.ResourceNotFoundException;
import com.qingwenwei.persistence.model.User;
import com.qingwenwei.service.UserService;
import com.qingwenwei.util.NewUserFormValidator;
import com.qingwenwei.web.dto.UserRegistrationDto;
import com.qingwenwei.web.dto.UserSettingsDto;
import org.apache.catalina.servlet4preview.http.HttpServletRequest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*; import javax.validation.Valid;
import java.util.Map; @Controller
public class UserController { Logger logger = LogManager.getLogger(UserController.class);
// private static final Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired
private UserService userService; @Autowired
private NewUserFormValidator userValidator; @RequestMapping(value = "/user/{userId}", method = RequestMethod.GET)
public String showUserProfilePage(@RequestParam(value = "tab", required = false) String tabType,
@PathVariable Long userId, Model model) {
if (null == userId) {
throw new BadRequestException("Path variable userId cound not be null.");
}
Map<String, Object> attributes = this.userService.getUserProfileAndPostsByUserIdByTabType(userId, tabType);
if (null == attributes) {
throw new ResourceNotFoundException("attributes not found.");
}
model.addAllAttributes(attributes);
return "forum/user-profile";
} @RequestMapping(value = "/user/registration", method = RequestMethod.GET)
public String showRegistrationPage(Model model) {
model.addAttribute("userDto", new UserRegistrationDto());
return "forum/user-registration"; //注册页面
} @RequestMapping(value = "/user/registration", method = RequestMethod.POST) //提交注册
public String registerNewUser(@Valid @ModelAttribute("userDto") UserRegistrationDto userDto,
BindingResult bindingResult, Model model, HttpServletRequest request) {
/*
* form validation, check username and email uniqueness
*/
this.userValidator.validate(userDto, bindingResult);
if (bindingResult.hasErrors()) {
logger.info("BindingResult has errors >> " + bindingResult.getFieldError());
return "forum/user-registration";
}
logger.debug("注册"+userDto.getMatchingPassword());
Map<String, Object> attributes = this.userService.registerUserAccount(userDto, request);
if (null == attributes) {
throw new ResourceNotFoundException("attributes not found.");
}
model.addAllAttributes(attributes);
return "forum/user-registration-result";
} @RequestMapping(value = "/user/login", method = RequestMethod.GET)
public String displayLoginPage(Model model) {
logger.debug("user/login登录");
model.addAttribute("title", "用户登陆");
return "forum/user-login"; //登录界面,验证没通过。
} @RequestMapping(value = "/user/login-success", method = RequestMethod.GET)
public String showAdminPage() {
logger.debug("登录成功");
return "forum/user-login";
// return "/";
} @RequestMapping(value = "/confirm", method = RequestMethod.GET)
public String confirmRegistration(@RequestParam("token") String token) {
return "forum/confirmation";
} @RequestMapping(value = "/confirm", method = RequestMethod.POST)
public String processConfirmation() {
return "forum/confirmation";
} @RequestMapping(value = "/user/settings", method = RequestMethod.GET)
public String showUserSettingsPage(Model model) {
Map<String, Object> attributes = this.userService.getUserSettingPage();
if (null == attributes) {
throw new ResourceNotFoundException("attributes not found.");
}
model.addAllAttributes(attributes);
return "forum/user-settings";
} @RequestMapping(value = "/user/settings", method = RequestMethod.POST)
public String handleFileUpload(@ModelAttribute("userSettingsDto") UserSettingsDto userSettingsDto, Model model) {
// User byConfirmationToken = userService.findByConfirmationToken(userSettingsDto.getPasswordConfirmation());
// logger.debug(byConfirmationToken.getPassword());
// logger.debug(userSettingsDto.getPassword()); if (null == userSettingsDto) {
throw new BadRequestException("UserSettingsDto cound not be null.");
}
Map<String, Object> attributes = this.userService.updateUserProfile(userSettingsDto);
if (null == attributes) {
throw new ResourceNotFoundException("attributes not found.");
}
model.addAllAttributes(attributes);
return "forum/user-settings";
} }
5:UserService.java UserServiceImpl.java
package com.qingwenwei.service; import com.qingwenwei.persistence.model.User;
import com.qingwenwei.web.dto.UserRegistrationDto;
import com.qingwenwei.web.dto.UserSettingsDto; import javax.servlet.http.HttpServletRequest;
import java.util.Map; public interface UserService { int save(User user); User findById(Long id); User findByUsername(String username); User findByEmail(String email); User findByConfirmationToken(String confirmationToken); User findAuthenticatedUser(); Map<String, Object> getUserProfileAndPostsByUserIdByTabType(Long userId, String tabType); Map<String, Object> updateUserProfile(UserSettingsDto newUserSettingsForm); Map<String, Object> getUserSettingPage(); Map<String, Object> registerUserAccount(UserRegistrationDto userDto, HttpServletRequest request); }
package com.qingwenwei.service.impl; import com.qingwenwei.event.OnRegistrationCompleteEvent;
import com.qingwenwei.persistence.dao.CommentMapper;
import com.qingwenwei.persistence.dao.PostMapper;
import com.qingwenwei.persistence.dao.UserMapper;
import com.qingwenwei.persistence.model.Comment;
import com.qingwenwei.persistence.model.Post;
import com.qingwenwei.persistence.model.User;
import com.qingwenwei.service.StorageService;
import com.qingwenwei.service.UserService;
import com.qingwenwei.web.dto.UserRegistrationDto;
import com.qingwenwei.web.dto.UserSettingsDto;
import org.apache.logging.log4j.LogManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.util.*; @Service("userService")
public class UserServiceImpl implements UserService { // private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
org.apache.logging.log4j.Logger logger = LogManager.getLogger(UserServiceImpl.class);
@Autowired
private UserMapper userMapper; @Autowired
private PostMapper postMapper; @Autowired
private CommentMapper commentMapper; // @Autowired
// private VerificationTokenMapper verificationTokenMapper; @Autowired
private StorageService storageService; @Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder; @Autowired
private ApplicationEventPublisher evenPublisher; @Override
public User findById(Long id) {
return userMapper.findById(id);
} @Override
public User findByEmail(String email) {
return userMapper.findByEmail(email);
} @Override
public User findByConfirmationToken(String confirmationToken) {
return userMapper.findByConfirmationToken(confirmationToken);
} @Override
public User findByUsername(String username) {
return userMapper.findByUsername(username);
} @Override //重置密码
public int save(User user) {
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword())); //保存时应该将密码编码
return userMapper.save(user);
}
// @Override
// public int save(User user) {
// user.setPassword(user.getPassword());
// return userMapper.save(user);
// } @Override
public Map<String, Object> getUserProfileAndPostsByUserIdByTabType(Long userId, String tabType) {
if (null == userId) {
return null;
}
User user = this.userMapper.findById(userId);
if (null == user) {
return null;
}
Map<String, Object> attributes = new HashMap<>();
attributes.put("user", user);
String activeTab = tabType == null ? "posts" : tabType;
if ("posts".equalsIgnoreCase(activeTab)) {
List<Post> posts = this.postMapper.findPostsByUserId(userId);
attributes.put("posts", posts);
} else if ("comments".equalsIgnoreCase(activeTab)) {
List<Comment> comments = this.commentMapper.findCommentsByUserId(userId);
attributes.put("comments", comments);
}
attributes.put("activeTab", activeTab);
return attributes;
} @Override
public User findAuthenticatedUser() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();
return this.userMapper.findByUsername(username);
} /**
* 更新用户profile
* @param userSettingsDto
* @return
*/
@Override
public Map<String, Object> updateUserProfile(UserSettingsDto userSettingsDto) {
Map<String, Object> attributes = new HashMap<>();
// String authenticatedUsername = this.findAuthenticatedUser().getUsername();
User authenticatedUser = this.findAuthenticatedUser(); String authenticatedUsername = authenticatedUser.getUsername();
String password = authenticatedUser.getPassword();
logger.debug("passward"+password);
if (null == authenticatedUsername || authenticatedUsername.equalsIgnoreCase("")
|| null == userSettingsDto
|| userSettingsDto.getEmail().isEmpty()
|| userSettingsDto.getEmail().equals("")) {
attributes.put("uploadResultMessage", "uploadFailure");
return attributes;
}
// update user profile
User user = this.storageService.store(userSettingsDto.getAvatar(), authenticatedUsername);
if (null == user) {
attributes.put("uploadResultMessage", "uploadFailure");
user = this.findAuthenticatedUser(); // find authenticated user if no user found
}
user.setPassword(password);
user.setEmail(userSettingsDto.getEmail());
user.setBio(userSettingsDto.getBio()); this.userMapper.update(user); // return attributes
attributes.put("user", user);
attributes.put("uploadResultMessage", "uploadSuccess");
return attributes;
} @Override
public Map<String, Object> getUserSettingPage() {
User user = this.findAuthenticatedUser();
UserSettingsDto newUserSettingsForm = new UserSettingsDto();
newUserSettingsForm.setBio(user.getBio());
newUserSettingsForm.setEmail(user.getEmail());
Map<String, Object> attributes = new HashMap<>();
attributes.put("user", user);
attributes.put("userSettingsDto", newUserSettingsForm);
return attributes;
} @Override
public Map<String, Object> registerUserAccount(UserRegistrationDto userDto, HttpServletRequest request) {
Map<String, Object> attributes = new HashMap<>(); // save newly registered user
User user = new User(); user.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword())); //保存时应该将密码编码 // user.setPassword(userDto.getPassword());
user.setUsername(userDto.getUsername());
user.setEmail(userDto.getEmail());
user.setDateCreated(new Timestamp(System.currentTimeMillis()));
user.activated(true);
user.setRoles(User.USER);
user.setConfirmationToken(UUID.randomUUID().toString()); // save new user and get number of affected row
logger.debug("用户注册");
int affectedRow = userMapper.save(user);
logger.debug("用户注册成功");
// publish registration event
String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort();
Locale locale = request.getLocale();
OnRegistrationCompleteEvent event = new OnRegistrationCompleteEvent(user.getUsername(), appUrl, locale);
this.evenPublisher.publishEvent(event); // populate attributes
String registrationResult = affectedRow == 1 ? "success" : "failure";
attributes.put("userRegistrationResult", registrationResult);
return attributes;
} }
6:UserMapper.java
package com.qingwenwei.persistence.dao; import com.qingwenwei.persistence.model.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper
public interface UserMapper { int save(@Param("user") User user); int update(@Param("user") User user); List<User> findAll(); User findById(Long id); User findByUsername(String username); User findByEmail(String email); User findByConfirmationToken(String confirmationToken); }
7;UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qingwenwei.persistence.dao.UserMapper"> <resultMap id="UserResultMap" type="com.qingwenwei.persistence.model.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="email" column="email"/>
<result property="confirmationToken" column="confirmation_token"/>
<result property="activated" column="activated"/>
<result property="dateCreated" column="date_created"/>
<result property="avatarLocation" column="avatar_location"/>
<result property="bio" column="bio"/>
</resultMap> <sql id="baseColumns" >
id, username, password, email, activated, date_created, avatar_location, bio,roles
</sql>
<insert id="save" parameterType="com.qingwenwei.persistence.model.User">
INSERT INTO `T_USER`
(
username,
password,
email,
confirmation_token,
activated,
date_created,
avatar_location,
bio,
roles
)
VALUES
(
#{user.username},
#{user.password},
#{user.email},
#{user.confirmationToken},
#{user.activated},
#{user.dateCreated},
#{user.avatarLocation},
#{user.bio},
#{user.roles}
)
</insert> <select id="findById" parameterType="Long" resultMap="UserResultMap">
SELECT
id,
username,
password,
email,
activated,
date_created,
avatar_location,
bio,
roles
FROM T_USER
WHERE id = #{id}
</select> <select id="findByUsername" parameterType="String" resultMap="UserResultMap">
SELECT
id,
username,
password,
email,
activated,
date_created,
avatar_location,
bio,
roles
FROM T_USER
WHERE username = #{username}
</select> <select id="findByEmail" parameterType="String" resultMap="UserResultMap">
SELECT
id,
username,
password,
email,
activated,
date_created,
avatar_location,
bio,
roles
FROM T_USER
WHERE email = #{email}
</select> <select id="findByConfirmationToken" parameterType="String" resultMap="UserResultMap">
SELECT
id,
username,
password,
email,
activated,
date_created,
avatar_location,
bio,
confirmation_token,
roles
FROM T_USER
WHERE confirmation_token = #{confirmationToken}
</select> <select id="findAll" resultMap="UserResultMap">
SELECT
id,
username,
password,
email,
activated,
date_created,
avatar_location,
bio,
confirmation_token,
roles
FROM T_USER
</select> <update id="update" parameterType="com.qingwenwei.persistence.model.User">
UPDATE T_USER SET
password = #{user.password},
email = #{user.email},
date_created = #{user.dateCreated},
avatar_location = #{user.avatarLocation},
bio = #{user.bio}
WHERE id = #{user.id}
</update> </mapper>
8;User.java
package com.qingwenwei.persistence.model; import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set; public class User implements Serializable { private static final long serialVersionUID = 1L; // constants
public static String USER = "USER"; //两种用户
public static String ADMIN = "ADMIN"; private Long id;
private String username;
private String password;
private String email;
private String confirmationToken;
private Long activated;
private Timestamp dateCreated;
private String avatarLocation;
private String bio;
private String roles; public User() { } public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String userName) {
this.username = userName;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
} public String getConfirmationToken() {
return confirmationToken;
} public void setConfirmationToken(String confirmationToken) {
this.confirmationToken = confirmationToken;
} public Long getActivated() {
return activated;
} public void setActivated(Long activated) {
this.activated = activated;
} public static void setUSER(String USER) {
User.USER = USER;
} public static void setADMIN(String ADMIN) {
User.ADMIN = ADMIN;
} public static long getSerialVersionUID() {
return serialVersionUID; } public static String getUSER() {
return USER;
} public static String getADMIN() {
return ADMIN;
} public Timestamp getDateCreated() {
return dateCreated;
} public void setDateCreated(Timestamp dateCreated) {
this.dateCreated = dateCreated;
} public String getAvatarLocation() {
return avatarLocation;
} public void setAvatarLocation(String avatarLocation) {
this.avatarLocation = avatarLocation;
} public String getBio() {
return bio;
} public void setBio(String bio) {
this.bio = bio;
} public String getRoles() {
return roles;
} public void setRoles(String roles) {
this.roles = roles;
} //赋予该用户的角色 public Set<String> getRolesSet() {
if (null == roles) {
return null;
}
return Collections.unmodifiableSet(
new HashSet<String>(Arrays.asList(getRoles().split(","))));
} public void addRole(String role) {
String currRoles = this.getRoles();
if (null == currRoles || this.getRoles().contains(role)) {
return;
}
this.setRoles(currRoles + "," + role);
} public void activated(boolean activated) {
this.setActivated(activated == true ? 1L : 0L);
} @Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", email=" + email
+ ", confirmationToken=" + confirmationToken + ", activated=" + activated + ", dateCreated="
+ dateCreated + ", avatarLocation=" + avatarLocation + ", bio=" + bio + ", roles=" + roles + "]";
} }
9:配置成功。