当前位置:网站首页>Microservice architecture practice: business management background and SSO design: SSO design
Microservice architecture practice: business management background and SSO design: SSO design
2022-06-26 16:59:00 【Seconds to write code】
SSO Design
Spring Security Is a powerful 、 Customizable authentication and access control framework .Spring Security OAuth2 It's based on Spring The framework supports third-party application authorization tool components . By using Spring Security OAuth2, We can perform single sign on in the merchant background (SSO) Design , So as to provide system integration for multiple microservice applications , Use unified security control management .
SSO The design is divided into two parts: server and client .SSO The server provides unified access control and authorization authentication services for each application , It's a Web UI Microservice application , In the module merchant-sso Development in , Contains the user login design 、 Home page design and authentication service design .SSO A client is a program that provides local services to users
SSO Basic configuration
SSO Basic configuration and general Web UI The application project configuration is basically the same , That is to say Web UI Based on the application project configuration , increase Spring Cloud OAuth2 The dependent quotation of , The code is as follows :
<dependency>
<group Id>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>This component already contains Security and OAuth2 Two component systems , among ,Security Provides access control functions ,OAuth2 It provides third-party application authorization and authentication services .
In the application's configuration file application.yml in , Set up SSO Service port of the application , And set a cookie Save the user's login information , The code is as follows :
server:
port:8000
session:
cookie:
name: SESSIONIDTo ensure that third-party applications can be accessed normally after authorization , We must add access to the configuration file SSO The client returns a list of addresses , And use the correct format “http:/l Domain name or IP: port /login” To set , The code is as follows ;
#SSo The client returns a list of addresses ssoclient:
redirecturis:
- http://localhost:8081/login- http://127.0.0.1:8081/1oginsso Third party application authorization design
To give access to SSO Third party applications for ( This refers to access SSO Other microservice applications for services ) To authorize , We created a configuration class AuthServerConfig, It inherited
AuthorizationServerConfigurerAdapter, The code is as follows :
@Configuration
@EnableAuthorizationServer
@EnableConfigurationProperties(clienturls.class)
public class authServerConfig extends AuthorizationServerConfigurerAdapter
CAutowired
private Clienturls clienturls;
@Override
public void configure (AuthorizationServerSecurityConfigurer oauthServer)throws Exception {
oauthServer.tokenKeyAccess( "permitAll ()")
.checkTokenAccess("isAuthenticated()");
@override
public void configure (ClientDetailsServiceConfigurer clients) throwsException {
clients.inMemory()
.withClient ( "ssoclient")
.secret(passwordEncoder ().encode ("ssosecret")).authorizedGrantTypes ("authorization_code").scopes ( "user_info")
.autoApprove(true)
.redirectUris(clienturls.getRedirecturis());
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter. setSigningKey ( "demoSige");
return converter;
}
aoverride
public void configure(AuthorizationServerEndpointsConfigurer endpoints)throws Exception {
endpoints.accessTokenConverter(jwtAccessTokenConverter());
}
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}In the configuration class above , It includes the following main functions :
(1) Using annotations @EnableAuthorizationServer Turn on SSO The function of the server .(2) Rewrite the first configure, Turn on use Token The function of authorizing .
(3) Rewrite the second configure, Specify the form page authorization method for the client , namely authorization_code, And set the user name and password used for client authorization as ssoclient and ssosecret. meanwhile , Import the client return address list in the configuration , And set the client return address list as redirectUris. in addition , adopt autoApprove(true) Set to automatically confirm authorization , The steps that must be confirmed manually during client authorization are omitted .
(4) Rewrite the third configure, Use safe JwtAccessToken. Here is the use of the key , We simply use one text demoSige, If you want to use a safer way , You can use KeyStore Generate keys for configuration .
sso Login authentication design
The following provides a login interface , It is used to receive the user name, password and other information entered by the user , Implement user login operation . In login authentication , Use Spring Security Verify user name and password .
Create a MyUserDetails class , Realization Spring Security Of UserDetails, The code is as follows :
public class MyUserDetails implements UserDetails {
private string username;
private String password;
private Collection<? extends GrantedAuthority> authorities;
private User user;
public MyUserDetails(String username, String password, collection<? extendsGrantedAuthority>authorities, User user){
this.username = username;
this.password = password;
this.authorities = authorities;this.user = user;
}
...
}In this way, we can import our customized user system , Provide to Spring Security Certified .
Create a MyUserDetailsService class , Realization Spring Security Of UserDetailsService, Provide user information and import user roles for the following authentication services , The code is as follows :
@component
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserService userService;
@override
public UserDetails loadUserByUsername (String username) throwsUsernameNotFoundException {
User user = userService.findByName (username);
if(user==nul1){
throw new UsernameNotFoundException(" The user doesn't exist !");
}
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
List<Role> roles =user.getRoles ();
if(roles !=null)
{
for(Role role : roles) {
SimpleGrantedAuthority authority = new
SimpleGrantedAuthority(role.getName ());
authorities.add(authority);
}
}
MyUserDetails myUserDetails = new MyUserDetails (username,
user.getPassword(),authorities, user);
return myUserDetails;
}
}such , When Spring Security When authenticating , We will call our users and get the relevant roles , This completes the user name and password verification at login , And configure corresponding permissions for users .
In order to make the above design effective , We also need to create a configuration class , namely SecurityConfng tip o Dagger inheritance 」SprngSecurity Of
WebSecurityConfigurerAdapter, The code is as follows :
@Configuration
public class SecurityConfig extends webSecurityConfigurerAdapter
@Autowired
private MyUserDetailsService myUserDetailsService;
@Autowired
@Qualifier("dataSource")
private DataSource dataSource;
@Bean(name = BeanIds.AUTHENTICATION MANAGER)Goverride
public AuthenticationManager authenticationManagerBean () throws Exception
return super.authenticationManagerBean();
@override
protected void configure (AuthenticationManagerBuilder auth)
throws Exception {
auth //lremember me
.eraseCredentials(false)
.userDetailsService (myUserDetailsService).passwordEncoder (new
BCryptPasswordEncoder());
@Override
protected void configure(HttpSecurity http) throws Exception
http.antMatcher("/**")
.authorizeRequests().antMatchers( "/login").permitAl1()
.antMatchers(" /images/**", "/checkcode", "/scripts/*
"/styles/**")
.permitAll().anyRequest().authenticated()
.and ().sessionManagement ().sessionCreationPolicy(SessionCreati
onPolicy.NEVER)
.and(.exceptionHandling().accessDeniedPage ("/deny")
.and().rememberMe ().tokenValiditySeconds (86400).tokenRepositor
y(tokenRepository())
.and()
.formLogin().loginPage ("/login" ).permitAll ().successHandler(lo
ginsuccessHandler())
.and() .logout()
.logoutUrl("/logout").permitAll().logoutSuccessUrl ("/signout");
}
@Bean
public JdbcTokenRepositoryImpl tokenRepository()
JdbcTokenRepositoryImpl jtr = new JdbcTokenRepositoryImpl()jtr.setDataSource(dataSource);
return jtr;
}
@Bean
public LoginSuccessHandler loginsuccessHandler(){
return new LoginSuccessHandler();
}
}In this configuration class , The following settings are made :
(1) Set the user service as defined above MyUserDetailsService.
(2) Specify the login page link as /login, In this way, the view file can be specified through the controller design .
(3) Specify the handler for successful login loginSuccessHandler.
4) Ignore the verification of static resources such as images .
(5) Specify the error prompt link to deny access /deny.
(6) Use rememberMe() Set to remember the user's login status .
(7) Specifies that the local data source is used to store the temporary data of user login status .
Design for the above configuration class , We create a controller , Set up a login link /login, And specify an interface design page for it login.html, The code is as follows :
@Controller
public class LoginController {
@RequestMapping( "/1ogin")public String login(){
return "login";
)
}On the interface design page login.html in , Mainly use a form design , Provide a login interface with user name, password and other input controls , The code is as follows :
...
<form th:action="@{/login}" id="loginForm" method="post">
<div class="loginTit png"></div>
<ul class="infList">
<li class="grayBox">
<label for="username" class="username-icon"></label><input id="username" class="username" name="username"
type="text" placeholder=" Your user name "/>
<div class="close png hide"></div></li>
<li class="grayBox">
<label class="pwd-icon" id="pwd"></label>
<input id="password" name="password" class="pwd"
type="password" placeholder=" The login password "/>
<div class="close png hide"></div></li>
<li class="" id="isCheckCode" style="display: none; ">
<label class="validateLabel" ></label>
<input id="checkCode" name=" checkCode" class="checkCo
type-"text" placeholder=" Verification Code "/>
<img onclick="reloadImg ();" style="cursor: pointer"
th:src="e{/images/imagecode)" id="validateImg" alt=" Verification Code "class="codePic"title-" Verification Code . Click here to update the verification code ."/>
<a class="getother" href="javascript:void(0);"
onclick="reloadImg ();" title=" Click here to update the verification code ."> to update </a>
</li>
</ul>
<ul class="infList reloadBtn" style="display: none; ">
<li>
<a href="javascript:void(0);" onclick="tologin();"> This page
It's invalid . Please click here to log in again .</a>
</li>
</u.l>
<divclass="loginBtnBo×">
div class="check-box"><input type="hidden" value="O"
id="remember-me" name="remember-me" onclick="if(this.checked) {this.value
1}else {this.value=0}"/>span class="toggleCheck no-check" id="repwd"></span> Remember me </div>
<input type="button" id="loginBtn" onclick="verSubmit()
value=" Sign in "class="loginBtn png"/>
</div>
</form>
...Complete the design of the login interface , The display effect is similar to a floating window , Pictured 10-4 Shown .

Description of verification code
When the user logs in for the first time , You can't see the verification code ; When the user fails to log in for the first time and needs to log in again , Will be asked to enter the verification code .
About the implementation of verification code , Here are two main explanations , That is, the output of the verification code and the verification of the verification code .
The output of the verification code is an image , The code is as follows :
@RequestMapping (value = " /images/imagecode")
public String imagecode (HttpServletRequest request, HttpServletResponseresponse)
throws Exception {
OutputStream os = response.getOutputStream();
Map<String, 0bject> map = ImageCode.getImageCode(60,20,os);
String simpleCaptcha = "simpleCaptcha";
request.getSession().setAttribute(simpleCaptcha,map.get("strEnsure") .toString().toLowerCase());
request.getSession().setAttribute ("codeTime", new Date() .getTime());
try {
ImageIO.write ((BufferedImage)map.get ("image"),"JPEG",0S);]catch(IOException e){
return "";
}
return null;
}That is, use... On the page “limages/imagecode” This link , You can return a verification code image consisting of several random numbers . When outputting the verification code , Use session Save the data of the verification code , Provide the basis for the verification code inspection in the next step .
About the verification of verification code , The implementation code is as follows :
@RequestMapping(value ="/checkcode")CResponseBody
public String checkcode (HttpServletRequest request,HttpSession session)
throws Exception {
String checkCode = request.getParameter("checkCode");
Object simple = session.getAttribute ("simpleCaptcha");// Verification code object if(simple == null){
request.setAttribute ("errorMsg"," The verification code has failed , Please re-enter !");return" The verification code has failed , Please re-enter !";
String captcha = simple.toString();Date now = new Date();
Long codeTime = Long.valueof(session.getAttribute ("codeTime")+"");if(StringUtils.isEmpty(checkCode) l captcha ==
null !(checkCode.equalsIgnoreCase(captcha))){
request.setAttribute( "errorMsg"," Verification code error !");return" Verification code error !";
}else if ((now.getTime ()-codeTime)/ 1000/60 >5)(// The valid length of the verification code is 5mi
request.setAttribute("errorMsg""," The verification code has failed , Please re-enter !");
return" The verification code has failed , Please re-enter !";
}else {
session.removeAttribute( "simpleCaptcha");return "1";
}
}Match the user input with the above session Compare the saved data , If the same , It can pass the inspection .
After completing the above design , When the user fails to log in for the first time , It will display as shown in the figure 10-5 The login interface shown in .

ssO Home page design
If it is in an access SSO Login in the third-party application of the service , After successful login ,SSO The server will return to the relevant application according to the link address of the application . If it's in SSO Login in the server , By default, it returns SSO The home page of the server . In the homepage design , We provide links to other applications .
SSO Home page design , It is generally composed of two parts . The first part is the design of a controller , The implementation code is as follows :
@controller
public class LoginController {
@ReguestMapping ("/")
public String index (ModelMap model, Principal principal) throws Exception{
MyUserDetails myUserDetails = (MyUserDetails)
SecurityContextHolder.getContext () .getAuthentication().getPrincipal();
User user = myUserDetails.getUser();
// List of categories ( Top menu )
List<Kind> kindList =new ArrayList<>();List<Long> kindIds = new ArrayList<>();for(Role role : user.getRoles ()){
for(Resource resource : role.getResources()){
// duplicate removal , Get a list of categories
Long kindId = resource.getModel().getKind().getId();if(! kindIds.contains(kindId)){
kindList.add(resource.getModel ().getKind());
kindIds.add (kindId);
}
}
}
model .addAttribute("kinds", kindList);
model . addAttribute("principal", principal);return "home";
}
}First , adopt SecurityContextHolder Get the complete information of the login user . then , According to login user , Relationships around users , You can sort out the top-level menus that users can access . Last , Use the classification list kinds Make this top-level menu available to the home page view .
The second part is a page view design , Among them, the design of dealing with the classification list part , stay SSO Home page home.html The navigation part of , The code is as follows :
<div class="new-icon" th:each="kind: $ {kinds}">
<div class="icon-pic">
<p><a
th:href="${'javascript:gotoService ("'+kind.link+' ", "
");')" class="linka" ><img src="/images/home/BigIconFirm. png" /</a></p>
</div>
<div class="icon-txt">
<dl>
<dt><p><a
th:hrefe"'javascript:gotoService (1''+$(kind.link}+'\',N' ');'" class="linka"th:text="${kind.name}"></a></p>
<span><img
srC=" /images/home/FourStar.jpg"/></span>
</dt></dl></div></div>It's used here Thymeleaf A loop statement of th:each, Display each record contained in the classification list on the page . Each record contains an image and a text link . among , Access to each link , Use gotoService Function to jump to the page .
After completing the above design , You can do a simple test .
start-up merchant-sso application , Enter the link shown below in the browser :http://localhost:8000
When I open the link , You can enter the login interface . Enter the user name and password generated in the previous unit test on the login interface , namely “admin/123456”. After successful login , You can open SSO The home page of , Pictured 10-6 Shown .

Be careful : chart 10-6 List of apps shown in , Will be determined by the permissions the user has . Suppose we assign more permissions to a user , Then the user will get more access to resources , Pictured 10-7 Shown .

In this article, we will explain the content of business management background and sso Design : SSO Design
- The next article will explain the background of business management and sso Design :SSO Client design ;
- Friends who think the article is good can forward this article and pay attention to Xiaobian ;
- Thank you for your support !
边栏推荐
- proxy
- [matlab project practice] prediction of remaining service life of lithium ion battery based on convolutional neural network and bidirectional long short time (cnn-lstm) fusion
- Teach you to learn dapr - 8 binding
- Calculate the average of N numbers in the group indexed by the formal parameter x, move the data less than the average in the group indexed to the front of the array, and move the data greater than or
- Niuke Xiaobai monthly race 50
- Web3 decentralized storage ecological landscape
- 知道这几个命令让你掌握Shell自带工具
- 建立自己的网站(16)
- Teach you to learn dapr - 2 Must know concept
- Qt 5.9.8 安装教程
猜你喜欢

5G未平6G再启,中国引领无线通信,6G的最大优势在哪里?

JUnit unit test

C语言 头哥习题答案截图
Teach you to learn dapr - 6 Publish subscription

C language --- basic function realization of push box 01
![[Li Kou brush question] monotone stack: 84 The largest rectangle in the histogram](/img/75/440e515c82b5613b117728ba760786.png)
[Li Kou brush question] monotone stack: 84 The largest rectangle in the histogram

构造函数和析构函数

Basic requirements: 7 problems in singleton mode

Cuckoo filter for Chang'an chain transaction

Structure the graduation project of actual combat camp
随机推荐
Some instance methods of mono
Stm32h7b0 replaces the h750 program, causing the MCU to hang up and unable to burn the program
Find all primes less than or equal to Lim, store them in AA array, and return the number of primes
MS|谢黎炜组发现混合益生菌制剂及其代谢产物可缓解结肠炎
Calculate the sum of the main diagonals of the array
Day10 daily 3 questions (3): String Matching in array
Niuke programming problem -- dynamic programming of must brush 101 (a thorough understanding of dynamic programming)
知道这几个命令让你掌握Shell自带工具
r329(MAIX-II-A(M2A)资料汇总
Knowing these commands allows you to master shell's own tools
Niuke Xiaobai monthly race 50
A simple membership card management system based on Scala
Romance of the Three Kingdoms: responsibility chain model
Byte interview: two array interview questions, please accept
LeetCode Algorithm 24. Exchange the nodes in the linked list in pairs
Basic requirements: 7 problems in singleton mode
Redis' 43 serial cannons, try how many you can carry
Fgetc() reads content from file
STM32F103C8T6实现呼吸灯代码
Deployment and operation of mongodb partitioned cluster